From 3e78886a956f5e609f29e7e9319f7dab813ba4e3 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Wed, 15 Apr 2026 16:57:11 -0500 Subject: [PATCH] fix vkFlushMappedMemoryRanges and vkCmdBeginRendering validation errors --- include/collada/scene/vulkan.h | 1 + include/vulkan_helper.h | 24 +++++++++++++++++ src/collada/scene/vulkan.cpp | 47 +++++++++++++++++++--------------- src/main.cpp | 12 ++++++--- src/vulkan_helper.cpp | 5 ++-- 5 files changed, 62 insertions(+), 27 deletions(-) diff --git a/include/collada/scene/vulkan.h b/include/collada/scene/vulkan.h index 1821385..9da55a4 100644 --- a/include/collada/scene/vulkan.h +++ b/include/collada/scene/vulkan.h @@ -73,6 +73,7 @@ namespace collada::scene { } shaderData; struct { VkDeviceMemory memory; + VkDeviceSize memorySize; void * mappedData; struct { // must match perFrameDescriptorCount VkBuffer sceneBuffer; diff --git a/include/vulkan_helper.h b/include/vulkan_helper.h index a30d8b2..41f1aaf 100644 --- a/include/vulkan_helper.h +++ b/include/vulkan_helper.h @@ -2,6 +2,13 @@ #include +inline static constexpr VkDeviceSize roundDownAlignment(VkDeviceSize offset, VkDeviceSize alignment) +{ + // must be a power of two + assert(alignment && ((alignment & (alignment - 1)) == 0)); + return offset & ~(alignment - 1); +} + inline static constexpr VkDeviceSize roundAlignment(VkDeviceSize offset, VkDeviceSize alignment) { // must be a power of two @@ -9,6 +16,22 @@ inline static constexpr VkDeviceSize roundAlignment(VkDeviceSize offset, VkDevic return (offset + (alignment - 1)) & (-alignment); } +inline static constexpr void alignMappedMemoryRanges(uint32_t nonCoherentAtomSize, + VkDeviceSize memorySize, + uint32_t count, + VkMappedMemoryRange * ranges) +{ + for (uint32_t i = 0; i < count; i++) { + VkDeviceSize alignedOffset{ roundDownAlignment(ranges[i].offset, nonCoherentAtomSize) }; + VkDeviceSize alignedSize{ roundAlignment(ranges[i].size + (ranges[i].offset - alignedOffset), nonCoherentAtomSize) }; + if (alignedOffset + alignedSize > memorySize) { + alignedSize = VK_WHOLE_SIZE; + } + ranges[i].offset = alignedOffset; + ranges[i].size = alignedSize; + } +} + VkDeviceSize allocateFromMemoryRequirements(VkDevice device, VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties, VkMemoryRequirements const & memoryRequirements, @@ -18,6 +41,7 @@ VkDeviceSize allocateFromMemoryRequirements(VkDevice device, VkDeviceMemory * memory); VkDeviceSize allocateFromMemoryRequirements2(VkDevice device, + VkPhysicalDeviceProperties const & physicalDeviceProperties, VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties, VkMemoryPropertyFlags memoryPropertyFlags, VkMemoryAllocateFlags memoryAllocateFlags, diff --git a/src/collada/scene/vulkan.cpp b/src/collada/scene/vulkan.cpp index 442e7ce..0dc40a2 100644 --- a/src/collada/scene/vulkan.cpp +++ b/src/collada/scene/vulkan.cpp @@ -236,14 +236,15 @@ namespace collada::scene { VkMemoryPropertyFlags memoryPropertyFlags{ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT }; VkMemoryAllocateFlags memoryAllocateFlags{ }; - allocateFromMemoryRequirements2(device, - physicalDeviceMemoryProperties, - memoryPropertyFlags, - memoryAllocateFlags, - uniformBufferDescriptorCount, - memoryRequirements, - &shaderDataDevice.memory, - offsets); + shaderDataDevice.memorySize = allocateFromMemoryRequirements2(device, + physicalDeviceProperties, + physicalDeviceMemoryProperties, + memoryPropertyFlags, + memoryAllocateFlags, + uniformBufferDescriptorCount, + memoryRequirements, + &shaderDataDevice.memory, + offsets); VkDeviceSize offset{ 0 }; VkDeviceSize size{ VK_WHOLE_SIZE }; @@ -301,7 +302,7 @@ namespace collada::scene { }; VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .maxSets = 2, + .maxSets = maxFrames + 1, // +1 for descriptorSet1 .poolSizeCount = descriptorPoolSizesCount, .pPoolSizes = descriptorPoolSizes }; @@ -519,16 +520,20 @@ namespace collada::scene { // flush - VkDeviceSize materialColorsFlushSize{ shaderDataDevice.constant.materialColorsSize }; - VkMappedMemoryRange shaderDataMemoryRanges[1]{ + VkMappedMemoryRange mappedMemoryRanges[1]{ { .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, .memory = shaderDataDevice.memory, .offset = shaderDataDevice.constant.materialColorsOffset, - .size = roundAlignment(materialColorsFlushSize, physicalDeviceProperties.limits.nonCoherentAtomSize), + .size = shaderDataDevice.constant.materialColorsSize, }, }; - vkFlushMappedMemoryRanges(device, 1, shaderDataMemoryRanges); + alignMappedMemoryRanges(physicalDeviceProperties.limits.nonCoherentAtomSize, + shaderDataDevice.memorySize, + 1, mappedMemoryRanges); + //fprintf(stderr, "flush materials start %ld %ld %ld %ld : %ld\n", offset, size, alignedOffset, alignedSize, shaderDataDevice.memorySize); + vkFlushMappedMemoryRanges(device, 1, mappedMemoryRanges); + //fprintf(stderr, "flush materials end\n"); } ////////////////////////////////////////////////////////////////////// @@ -811,25 +816,25 @@ namespace collada::scene { // flush - VkDeviceSize sceneFlushSize{ shaderDataDevice.frame[frameIndex].sceneSize }; - VkDeviceSize nodesFlushSize{ shaderDataDevice.frame[frameIndex].nodesSize }; - //fprintf(stderr, "sceneFlushSize %ld\n", sceneFlushSize); - //fprintf(stderr, "nodesFlushSize %ld\n", nodesFlushSize); - VkMappedMemoryRange shaderDataMemoryRanges[2]{ + VkMappedMemoryRange mappedMemoryRanges[2]{ { .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, .memory = shaderDataDevice.memory, .offset = shaderDataDevice.frame[frameIndex].sceneOffset, - .size = roundAlignment(sceneFlushSize, physicalDeviceProperties.limits.nonCoherentAtomSize), + .size = shaderDataDevice.frame[frameIndex].sceneSize, }, { .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, .memory = shaderDataDevice.memory, .offset = shaderDataDevice.frame[frameIndex].nodesOffset, - .size = roundAlignment(nodesFlushSize, physicalDeviceProperties.limits.nonCoherentAtomSize), + .size = shaderDataDevice.frame[frameIndex].nodesSize, } }; - vkFlushMappedMemoryRanges(device, 2, shaderDataMemoryRanges); + alignMappedMemoryRanges(physicalDeviceProperties.limits.nonCoherentAtomSize, + shaderDataDevice.memorySize, + 2, + mappedMemoryRanges); + vkFlushMappedMemoryRanges(device, 2, mappedMemoryRanges); } void vulkan::draw_node(int32_t node_index, diff --git a/src/main.cpp b/src/main.cpp index 1e27400..e9afd2c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -200,10 +200,6 @@ void recreateSwapchain(VkSurfaceFormatKHR surfaceFormat, VkFormat depthFormat, V .width = surfaceCapabilities.currentExtent.width, .height = surfaceCapabilities.currentExtent.height, }; - if ((imageExtent.width == ~0u) && (imageExtent.width == ~0u)) { - imageExtent.width = windowSize.x; - imageExtent.height = windowSize.y; - } VkFormat imageFormat{ surfaceFormat.format }; VkColorSpaceKHR imageColorSpace{ surfaceFormat.colorSpace }; @@ -463,6 +459,10 @@ int main() SDL_CHECK(SDL_GetWindowSize(window, &windowSize.x, &windowSize.y)); VkSurfaceCapabilitiesKHR surfaceCapabilities{}; VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfaceCapabilities)); + if ((surfaceCapabilities.currentExtent.width == ~0u) && (surfaceCapabilities.currentExtent.width == ~0u)) { + surfaceCapabilities.currentExtent.width = windowSize.x; + surfaceCapabilities.currentExtent.height = windowSize.y; + } printf("surfaceCapabilities currentExtent %d %d\n", surfaceCapabilities.currentExtent.width, surfaceCapabilities.currentExtent.height); // surface format @@ -1623,6 +1623,10 @@ int main() updateSwapchain = false; VK_CHECK(vkDeviceWaitIdle(device)); VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfaceCapabilities)); + if ((surfaceCapabilities.currentExtent.width == ~0u) && (surfaceCapabilities.currentExtent.width == ~0u)) { + surfaceCapabilities.currentExtent.width = windowSize.x; + surfaceCapabilities.currentExtent.height = windowSize.y; + } recreateSwapchain(surfaceFormat, depthFormat, physicalDeviceMemoryProperties, surfaceCapabilities); } } diff --git a/src/vulkan_helper.cpp b/src/vulkan_helper.cpp index 4d8d30a..d50b17a 100644 --- a/src/vulkan_helper.cpp +++ b/src/vulkan_helper.cpp @@ -65,6 +65,7 @@ VkDeviceSize allocateFromMemoryRequirements(VkDevice device, } VkDeviceSize allocateFromMemoryRequirements2(VkDevice device, + VkPhysicalDeviceProperties const & physicalDeviceProperties, VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties, VkMemoryPropertyFlags memoryPropertyFlags, VkMemoryAllocateFlags memoryAllocateFlags, @@ -95,10 +96,10 @@ VkDeviceSize allocateFromMemoryRequirements2(VkDevice device, VkMemoryAllocateInfo memoryAllocateInfo{ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .pNext = &memoryAllocateFlagsInfo, - .allocationSize = offset, + .allocationSize = roundAlignment(offset, physicalDeviceProperties.limits.nonCoherentAtomSize), .memoryTypeIndex = memoryTypeIndex, }; VK_CHECK(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, memory)); - return offset; + return memoryAllocateInfo.allocationSize; }