diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.cpp index 0037a8fd..4140ff2b 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.cpp +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.cpp @@ -27,7 +27,7 @@ namespace Renderer { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 }, { VK_DESCRIPTOR_TYPE_SAMPLER, 100 } }; - constexpr u32 maxDescriptorSets = 128; + constexpr u32 maxDescriptorSets = 256; // [Temp descriptor sets] Per-frame transient pools, reset in FlipFrame once the slot's fence // guarantees the GPU is done with the previous frame's transient sets @@ -179,7 +179,7 @@ namespace Renderer const std::string& bufferName = _bufferHandler->GetBufferName(bufferID); std::string bindingName = (binding >= 0) ? GetBindingName(descriptorSet, static_cast(binding)) : "Unknown"; - NC_LOG_ERROR(" ({}) Set {} Buffer {} '{}' at binding {} '{}' needs {} permission", BindingSlotNames[slot], bufferIndex, bufferName, binding, bindingName, permissionName); + NC_LOG_ERROR(" ({}) Buffer {} '{}' at binding {} '{}' needs {} permission", BindingSlotNames[slot], bufferIndex, bufferName, binding, bindingName, permissionName); }); return didError; diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.cpp index bfa247a6..7b52f983 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.cpp +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.cpp @@ -487,7 +487,26 @@ namespace Renderer } //bindInfos.insert(bindInfos.end(), bindReflection.dataBindings.begin(), bindReflection.dataBindings.end()); - bindInfoPushConstants.insert(bindInfoPushConstants.end(), bindReflection.pushConstants.begin(), bindReflection.pushConstants.end()); + + // Merge push constants like the data bindings above: every reflected range gets + // the same blanket stage flags, and Vulkan forbids two ranges sharing a stage, so + // a block declared by both shaders must union into one range + for (const BindInfoPushConstant& pushConstant : bindReflection.pushConstants) + { + if (!bindInfoPushConstants.empty()) + { + BindInfoPushConstant& existing = bindInfoPushConstants[0]; + + u32 end = glm::max(existing.offset + existing.size, pushConstant.offset + pushConstant.size); + existing.offset = glm::min(existing.offset, pushConstant.offset); + existing.size = end - existing.offset; + existing.stageFlags |= pushConstant.stageFlags; + } + else + { + bindInfoPushConstants.push_back(pushConstant); + } + } } // Build the used-set bitmask from reflection. DEBUG is included: if a shader actively uses the DEBUG set we want diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.cpp index d4f2147d..5b44233a 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.cpp +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.cpp @@ -449,6 +449,7 @@ namespace Renderer deviceFeatures.features.depthClamp = VK_TRUE; deviceFeatures.features.shaderStorageImageReadWithoutFormat = VK_TRUE; deviceFeatures.features.shaderImageGatherExtended = VK_TRUE; + deviceFeatures.features.shaderClipDistance = VK_TRUE; // SVSM page draws clip to dirty rects via SV_ClipDistance deviceFeatures.pNext = &device11Features; CheckDeviceFeatureSupport(_physicalDevice, deviceFeatures); diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TimeQueryHandlerVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TimeQueryHandlerVK.cpp index 59e9d0f3..22a8d664 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TimeQueryHandlerVK.cpp +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TimeQueryHandlerVK.cpp @@ -28,7 +28,7 @@ namespace Renderer { VkQueryPool queryPool; - static const u32 NUM_TOTAL_TIMESTAMPS = 200; + static const u32 NUM_TOTAL_TIMESTAMPS = 300; u32 numTimestamps = 0; std::vector timeQueries; diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.cpp index f35e818f..d3c12941 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.cpp +++ b/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.cpp @@ -849,9 +849,16 @@ namespace Renderer } uvec2 extent = desc.extent; - if (extent == uvec2(0) && desc.renderTargets[0] != ImageMutableResource::Invalid()) + if (extent == uvec2(0)) { - extent = _imageHandler->GetDimensions(desc.MutableResourceToImageID(desc.renderTargets[0]), 0); + if (desc.renderTargets[0] != ImageMutableResource::Invalid()) + { + extent = _imageHandler->GetDimensions(desc.MutableResourceToImageID(desc.renderTargets[0]), 0); + } + else if (desc.depthStencil != DepthImageMutableResource::Invalid()) + { + extent = _imageHandler->GetDimensions(desc.MutableResourceToDepthImageID(desc.depthStencil)); + } } VkRenderingInfo renderInfo = {}; @@ -1733,12 +1740,15 @@ namespace Renderer } if ((from & BufferPassUsage::GRAPHICS) == BufferPassUsage::GRAPHICS) { - srcStageMask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + // DRAW_INDIRECT: the pass may have consumed the buffer as indirect draw args, a + // following write needs the execution dependency against that read (WAR) + srcStageMask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; bufferBarrier.srcAccessMask |= VK_ACCESS_SHADER_WRITE_BIT; } if ((from & BufferPassUsage::COMPUTE) == BufferPassUsage::COMPUTE) { - srcStageMask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + // Same for indirect dispatch args + srcStageMask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; bufferBarrier.srcAccessMask |= VK_ACCESS_SHADER_WRITE_BIT; }