summaryrefslogtreecommitdiff
path: root/src/window.cpp
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-03-03 14:03:21 -0500
committerJonathan Bradley <jcb@pikum.xyz>2025-03-03 14:03:21 -0500
commit24b7ea3d50ad6f6c50dfa354fe86c2af473a1a81 (patch)
tree0bfb4dfb4cc642f84eb9ab7d8f38d3805698bac3 /src/window.cpp
parent37347bf7811a5fa42c98e2a19adfee15252ee479 (diff)
pke: dynamic framebuffer length + VkPresentMode
Diffstat (limited to 'src/window.cpp')
-rw-r--r--src/window.cpp134
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);