diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-03-03 14:03:21 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-03-03 14:03:21 -0500 |
| commit | 24b7ea3d50ad6f6c50dfa354fe86c2af473a1a81 (patch) | |
| tree | 0bfb4dfb4cc642f84eb9ab7d8f38d3805698bac3 /src/window.cpp | |
| parent | 37347bf7811a5fa42c98e2a19adfee15252ee479 (diff) | |
pke: dynamic framebuffer length + VkPresentMode
Diffstat (limited to 'src/window.cpp')
| -rw-r--r-- | src/window.cpp | 134 |
1 files changed, 88 insertions, 46 deletions
diff --git a/src/window.cpp b/src/window.cpp index 5f04275..6c27238 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -769,15 +769,54 @@ void CreateImageResources_Inner(VkImageCreateInfo *imageCreateInfo, VkImageViewC } } +/* 2025-03-03 JCB + * I separated this out just so I could think about it more clearly. + * This function currently assumes that all of these present modes are available. + * My 7900XTX supports all 4 of these. + * This needs to be re-visited for platforms that have limited support. + * Issue: user requests unlocked framefrate without vsync, but doesn't support immediate mode. + * Is it better to give them mailbox to prefer unlimited framerate? + * Or let it fall back to fifo, ignoring the vsync setting? + * Note that `isFramerateUnlocked` is designed to limit framerate artificially. + */ +VkPresentModeKHR PickPresentMode(VkPresentModeKHR *present_modes, uint32_t n_present_modes) { + VkPresentModeKHR ret = VK_PRESENT_MODE_FIFO_KHR; + int32_t immediateIndex = -1; + int32_t fifoRelaxedIndex = -1; + int32_t mailboxIndex = -1; + for (uint32_t i = 0; i < n_present_modes; ++i) { + if (present_modes[i] == VkPresentModeKHR::VK_PRESENT_MODE_IMMEDIATE_KHR) { + immediateIndex = i; + } else if (present_modes[i] == VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR) { + mailboxIndex = i; + } else if (present_modes[i] == VkPresentModeKHR::VK_PRESENT_MODE_FIFO_RELAXED_KHR) { + fifoRelaxedIndex = i; + } + } + if (pkeSettings.graphicsSettings.isFramerateUnlocked == true && pkeSettings.graphicsSettings.isWaitingForVsync == true) { + if (mailboxIndex != -1) { + ret = VK_PRESENT_MODE_MAILBOX_KHR; + } + } else if (pkeSettings.graphicsSettings.isFramerateUnlocked == false && pkeSettings.graphicsSettings.isWaitingForVsync == true) { + // fifo + } else if (pkeSettings.graphicsSettings.isFramerateUnlocked == true && pkeSettings.graphicsSettings.isWaitingForVsync == false) { + if (immediateIndex != -1) { + ret = VK_PRESENT_MODE_IMMEDIATE_KHR; + } + } else { + if (fifoRelaxedIndex != -1) { + ret = VK_PRESENT_MODE_FIFO_RELAXED_KHR; + } + } + return ret; +} + void CreateSwapchain() { VkResult vkResult; VkSurfaceCapabilitiesKHR surfaceCapabilities; vkResult = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vkPhysicalDevice, vkSurfaceKHR, &surfaceCapabilities); - swapchainLength = surfaceCapabilities.minImageCount; assert(vkResult == VK_SUCCESS); - assert(swapchainLength >= surfaceCapabilities.minImageCount); - assert(surfaceCapabilities.maxImageCount == 0 || swapchainLength <= surfaceCapabilities.maxImageCount); if (selectedSurfaceIndex == -1u) { unsigned int surfaceFormatCounts; @@ -807,48 +846,14 @@ void CreateSwapchain() { Extent.width = PK_CLAMP(Extent.width, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width); Extent.height = PK_CLAMP(Extent.height, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height); - vkPresentModeKHR = VK_PRESENT_MODE_FIFO_KHR; - if (pkeSettings.graphicsSettings.isWaitingForVsync == false || pkeSettings.graphicsSettings.isFramerateUnlocked == true) { + { unsigned int presentModeCount = 0; vkResult = vkGetPhysicalDeviceSurfacePresentModesKHR(vkPhysicalDevice, vkSurfaceKHR, &presentModeCount, nullptr); assert(vkResult == VK_SUCCESS); VkPresentModeKHR *presentModes = pk_new<VkPresentModeKHR>(presentModeCount); vkResult = vkGetPhysicalDeviceSurfacePresentModesKHR(vkPhysicalDevice, vkSurfaceKHR, &presentModeCount, presentModes); assert(vkResult == VK_SUCCESS); - int32_t immediateIndex = -1; - int32_t fifoRelaxedIndex = -1; - /* - uint32_t mailboxIndex = -1; - uint32_t fifoIndex = -1; - */ - for (long i = 0; i < presentModeCount; ++i) { - if (presentModes[i] == VkPresentModeKHR::VK_PRESENT_MODE_IMMEDIATE_KHR) { - immediateIndex = i; - } - else if (presentModes[i] == VkPresentModeKHR::VK_PRESENT_MODE_FIFO_RELAXED_KHR) { - fifoRelaxedIndex = i; - } - /* - // TODO returns 5 swapchain images, which causes other unhandled issues - else if (presentModes[i] == VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR) { - mailboxIndex = i; - } - else if (presentModes[i] == VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR) { - fifoIndex = i; - } - */ - } - if (fifoRelaxedIndex != -1) { - vkPresentModeKHR = VK_PRESENT_MODE_FIFO_RELAXED_KHR; - } - /* - if (mailboxIndex != -1) { - vkPresentModeKHR = VK_PRESENT_MODE_MAILBOX_KHR; - } else - */ - if (immediateIndex != -1) { - vkPresentModeKHR = VK_PRESENT_MODE_IMMEDIATE_KHR; - } + vkPresentModeKHR = PickPresentMode(presentModes, presentModeCount); pk_delete<VkPresentModeKHR>(presentModes, presentModeCount); } @@ -857,7 +862,7 @@ void CreateSwapchain() { vkSwapchainCreateInfo.pNext = nullptr; vkSwapchainCreateInfo.flags = 0; vkSwapchainCreateInfo.surface = vkSurfaceKHR; - vkSwapchainCreateInfo.minImageCount = swapchainLength; + vkSwapchainCreateInfo.minImageCount = surfaceCapabilities.minImageCount; vkSwapchainCreateInfo.imageFormat = vkSurfaceFormatKHR.format; vkSwapchainCreateInfo.imageColorSpace = vkSurfaceFormatKHR.colorSpace; vkSwapchainCreateInfo.imageExtent = Extent; @@ -902,6 +907,8 @@ void CreateSwapchain() { prevSwapchainLength = swapchainLength; vkResult = vkGetSwapchainImagesKHR(vkDevice, vkSwapchainKHR, &swapchainLength, nullptr); assert(vkResult == VK_SUCCESS); + assert(swapchainLength >= surfaceCapabilities.minImageCount); + assert(surfaceCapabilities.maxImageCount == 0 || swapchainLength <= surfaceCapabilities.maxImageCount); pkvk_present.images = pk_new<VkImage>(swapchainLength); vkResult = vkGetSwapchainImagesKHR(vkDevice, vkSwapchainKHR, &swapchainLength, pkvk_present.images); assert(vkResult == VK_SUCCESS); @@ -1538,7 +1545,15 @@ void CreateCommandPool() { } } -void CreateCommandBuffer() { +void DestroyPresentCommandBuffers() { + if (pkvk_present.command_buffers != nullptr) { + vkFreeCommandBuffers(vkDevice, pkvk_shared.command_pool.graphics, prevSwapchainLength, pkvk_present.command_buffers); + pk_delete<VkCommandBuffer>(pkvk_present.command_buffers, prevSwapchainLength, MemBkt_Vulkan); + pkvk_present.command_buffers = nullptr; + } +} + +void CreatePresentCommandBuffers() { VkCommandBufferAllocateInfo allocInfo; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.pNext = nullptr; @@ -1551,7 +1566,15 @@ void CreateCommandBuffer() { if (result != VK_SUCCESS) { throw "failed to allocate command buffer"; } +} +void CreateCommandBuffers() { + VkResult result; + VkCommandBufferAllocateInfo allocInfo; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.pNext = nullptr; + allocInfo.commandPool = pkvk_shared.command_pool.graphics; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.commandBufferCount = 1; result = vkAllocateCommandBuffers(vkDevice, &allocInfo, &pkvk_shared.command_buffer.graphics); if (result != VK_SUCCESS) { @@ -1608,6 +1631,9 @@ void CreateUniformBuffers() { } void CreateSyncObjects() { + assert(pkvk_present.semaphores_image_available == nullptr || pkvk_present.semaphores_image_available == CAFE_BABE(VkSemaphore)); + assert(pkvk_present.semaphores_render_finished == nullptr || pkvk_present.semaphores_render_finished == CAFE_BABE(VkSemaphore)); + assert(pkvk_present.fences_in_flight == nullptr || pkvk_present.fences_in_flight == CAFE_BABE(VkFence)); VkSemaphoreCreateInfo semaphoreInfo; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreInfo.pNext = nullptr; @@ -2585,7 +2611,15 @@ void CreateGraphicsPipelines() { } } -void UpdateDebugGraphicsPipeline() { +void DestroyDebugDescriptors() { + if (pkeDebugHitbox.vkDescriptorPool != VK_NULL_HANDLE) { + vkDestroyDescriptorPool(vkDevice, pkeDebugHitbox.vkDescriptorPool, vkAllocator); + pk_delete<VkDescriptorSet>(pkeDebugHitbox.vkDescriptorSets, prevSwapchainLength); + pkeDebugHitbox.vkDescriptorSets = nullptr; + } +} + +void CreateDebugDescriptors() { // descriptor pool & sets VkDescriptorPoolSize descriptorPoolSizes[2]; descriptorPoolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; @@ -2624,7 +2658,9 @@ void UpdateDebugGraphicsPipeline() { pk_delete<VkDescriptorSetLayout>(descriptorSets, swapchainLength); // descriptorSets = CAFE_BABE(VkDescriptorSetLayout); assert(vkResult == VK_SUCCESS); +} +void UpdateDebugDescriptors() { VkWriteDescriptorSet *writeDescriptorSets = pk_new<VkWriteDescriptorSet>(2 * swapchainLength); for (long i = 0; i < 2 * swapchainLength; ++i) { writeDescriptorSets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -3148,6 +3184,8 @@ void RecreateSwapchain() { if (prevSwapchainLength != swapchainLength) { DestroySyncObjects(); DestroyPresentPipeline(); + DestroyPresentCommandBuffers(); + CreatePresentCommandBuffers(); CreatePresentPipeline(); CreateSyncObjects(); } @@ -3155,8 +3193,11 @@ void RecreateSwapchain() { UpdateCamera(); CreateFramebuffers(); if (prevSwapchainLength != swapchainLength) { + DestroyDebugDescriptors(); DestroyUniformBuffers(); CreateUniformBuffers(); + CreateDebugDescriptors(); + UpdateDebugDescriptors(); pk_ev_emit(pke_ev_mgr_id_window, pke_ev_id_framebuffer_length_changed, NULL); } shouldRecreateSwapchain = false; @@ -3194,11 +3235,13 @@ void CreateWindow(PKEWindowProperties wp) { UpdateCamera(); CreateFramebuffers(); CreateCommandPool(); - CreateCommandBuffer(); + CreatePresentCommandBuffers(); + CreateCommandBuffers(); CreateUniformBuffers(); CreateSyncObjects(); CreateGraphicsPipelines(); - UpdateDebugGraphicsPipeline(); + CreateDebugDescriptors(); + UpdateDebugDescriptors(); CreateImGui(); DetermineMonitor(); @@ -3213,8 +3256,7 @@ void DestroyWindow() { } DestroySwapchain(); - vkDestroyDescriptorPool(vkDevice, pkeDebugHitbox.vkDescriptorPool, vkAllocator); - pk_delete<VkDescriptorSet>(pkeDebugHitbox.vkDescriptorSets, swapchainLength); + DestroyDebugDescriptors(); vkDestroyBuffer(vkDevice, pkeDebugHitbox.indexBuffer, vkAllocator); vkDestroyBuffer(vkDevice, pkeDebugHitbox.uvBuffer, vkAllocator); |
