From 0fec698835bf7013aa91a92e15536c861a61503b Mon Sep 17 00:00:00 2001 From: Turanszki Janos Date: Mon, 19 Jul 2021 14:39:10 +0200 Subject: [PATCH] vulkan: shading rate fixes, zero-initialization of textures and buffers by default --- WickedEngine/RenderPath3D.cpp | 16 +-- WickedEngine/wiGraphics.h | 1 + WickedEngine/wiGraphicsDevice_Vulkan.cpp | 159 +++++++++++++++++------ WickedEngine/wiGraphicsDevice_Vulkan.h | 8 +- WickedEngine/wiRenderer.cpp | 18 +++ WickedEngine/wiVersion.cpp | 2 +- 6 files changed, 147 insertions(+), 57 deletions(-) diff --git a/WickedEngine/RenderPath3D.cpp b/WickedEngine/RenderPath3D.cpp index 8dba3158a..506ca449b 100644 --- a/WickedEngine/RenderPath3D.cpp +++ b/WickedEngine/RenderPath3D.cpp @@ -218,21 +218,13 @@ void RenderPath3D::ResizeBuffers() uint32_t tileSize = device->GetVariableRateShadingTileSize(); TextureDesc desc; - desc.layout = IMAGE_LAYOUT_UNDEFINED; - desc.BindFlags = BIND_UNORDERED_ACCESS; + desc.layout = IMAGE_LAYOUT_UNORDERED_ACCESS; + desc.BindFlags = BIND_UNORDERED_ACCESS | BIND_SHADING_RATE; desc.Format = FORMAT_R8_UINT; desc.Width = (internalResolution.x + tileSize - 1) / tileSize; desc.Height = (internalResolution.y + tileSize - 1) / tileSize; - std::vector data(desc.Width * desc.Height); - uint8_t default_shadingrate; - device->WriteShadingRateValue(SHADING_RATE_1X1, &default_shadingrate); - std::fill(data.begin(), data.end(), default_shadingrate); - - SubresourceData initData; - initData.pSysMem = data.data(); - initData.SysMemPitch = sizeof(uint8_t) * desc.Width; - device->CreateTexture(&desc, &initData, &rtShadingRate); + device->CreateTexture(&desc, nullptr, &rtShadingRate); device->SetName(&rtShadingRate, "rtShadingRate"); } @@ -344,7 +336,7 @@ void RenderPath3D::ResizeBuffers() if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)) { - desc.attachments.push_back(RenderPassAttachment::ShadingRateSource(&rtShadingRate, IMAGE_LAYOUT_UNDEFINED, IMAGE_LAYOUT_UNDEFINED)); + desc.attachments.push_back(RenderPassAttachment::ShadingRateSource(&rtShadingRate, IMAGE_LAYOUT_UNORDERED_ACCESS, IMAGE_LAYOUT_UNORDERED_ACCESS)); } device->CreateRenderPass(&desc, &renderpass_main); diff --git a/WickedEngine/wiGraphics.h b/WickedEngine/wiGraphics.h index f06ce9f9d..e65c512c4 100644 --- a/WickedEngine/wiGraphics.h +++ b/WickedEngine/wiGraphics.h @@ -336,6 +336,7 @@ namespace wiGraphics BIND_RENDER_TARGET = 1 << 5, BIND_DEPTH_STENCIL = 1 << 6, BIND_UNORDERED_ACCESS = 1 << 7, + BIND_SHADING_RATE = 1 << 8, }; enum CPU_ACCESS { diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 8c40e9760..c2175e69e 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -2528,16 +2528,16 @@ using namespace Vulkan_Internal; poolInfo.queueFamilyIndex = graphicsFamily; poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; - res = vkCreateCommandPool(device, &poolInfo, nullptr, &frames[fr].transitionCommandPool); + res = vkCreateCommandPool(device, &poolInfo, nullptr, &frames[fr].initCommandPool); assert(res == VK_SUCCESS); VkCommandBufferAllocateInfo commandBufferInfo = {}; commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; commandBufferInfo.commandBufferCount = 1; - commandBufferInfo.commandPool = frames[fr].transitionCommandPool; + commandBufferInfo.commandPool = frames[fr].initCommandPool; commandBufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - res = vkAllocateCommandBuffers(device, &commandBufferInfo, &frames[fr].transitionCommandBuffer); + res = vkAllocateCommandBuffers(device, &commandBufferInfo, &frames[fr].initCommandBuffer); assert(res == VK_SUCCESS); VkCommandBufferBeginInfo beginInfo = {}; @@ -2545,7 +2545,7 @@ using namespace Vulkan_Internal; beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; beginInfo.pInheritanceInfo = nullptr; // Optional - res = vkBeginCommandBuffer(frames[fr].transitionCommandBuffer, &beginInfo); + res = vkBeginCommandBuffer(frames[fr].initCommandBuffer, &beginInfo); assert(res == VK_SUCCESS); } } @@ -2608,7 +2608,7 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); // Transitions: - transitionLocker.lock(); + initLocker.lock(); { VkImageMemoryBarrier barrier = {}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; @@ -2624,15 +2624,40 @@ using namespace Vulkan_Internal; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.image = nullImage1D; barrier.subresourceRange.layerCount = 1; - transitions.push_back(barrier); + vkCmdPipelineBarrier( + GetFrameResources().initCommandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &barrier + ); barrier.image = nullImage2D; barrier.subresourceRange.layerCount = 6; - transitions.push_back(barrier); + vkCmdPipelineBarrier( + GetFrameResources().initCommandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &barrier + ); barrier.image = nullImage3D; barrier.subresourceRange.layerCount = 1; - transitions.push_back(barrier); + vkCmdPipelineBarrier( + GetFrameResources().initCommandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &barrier + ); } - transitionLocker.unlock(); + submit_inits = true; + initLocker.unlock(); VkImageViewCreateInfo viewInfo = {}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -2761,7 +2786,7 @@ using namespace Vulkan_Internal; vkDestroyCommandPool(device, frame.commandPools[cmd][queue], nullptr); } } - vkDestroyCommandPool(device, frame.transitionCommandPool, nullptr); + vkDestroyCommandPool(device, frame.initCommandPool, nullptr); for (auto& descriptormanager : frame.descriptors) { @@ -3289,6 +3314,20 @@ using namespace Vulkan_Internal; copyAllocator.submit(cmd); } } + else if(pDesc->Usage != USAGE_STAGING) + { + // zero-initialize: + initLocker.lock(); + vkCmdFillBuffer( + GetFrameResources().initCommandBuffer, + internal_state->resource, + 0, + VK_WHOLE_SIZE, + 0 + ); + submit_inits = true; + initLocker.unlock(); + } if (pDesc->Format == FORMAT_UNKNOWN) { @@ -3367,6 +3406,10 @@ using namespace Vulkan_Internal; imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; allocInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; } + if(pTexture->desc.BindFlags & BIND_SHADING_RATE) + { + imageInfo.usage |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR; + } imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; @@ -3532,9 +3575,18 @@ using namespace Vulkan_Internal; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = _ParseImageLayout(pTexture->desc.layout); - transitionLocker.lock(); - transitions.push_back(barrier); - transitionLocker.unlock(); + initLocker.lock(); + vkCmdPipelineBarrier( + GetFrameResources().initCommandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &barrier + ); + submit_inits = true; + initLocker.unlock(); } } else @@ -3565,9 +3617,49 @@ using namespace Vulkan_Internal; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - transitionLocker.lock(); - transitions.push_back(barrier); - transitionLocker.unlock(); + initLocker.lock(); + // zero initialize: + if (barrier.subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) + { + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + vkCmdPipelineBarrier( + GetFrameResources().initCommandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &barrier + ); + VkClearColorValue initialColor = {}; + VkImageSubresourceRange range = {}; + range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + range.baseArrayLayer = 0; + range.baseMipLevel = 0; + range.layerCount = barrier.subresourceRange.layerCount; + range.levelCount = barrier.subresourceRange.levelCount; + vkCmdClearColorImage( + GetFrameResources().initCommandBuffer, + internal_state->resource, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + &initialColor, + 1, &range + ); + + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = _ConvertImageLayout(pTexture->desc.layout); + } + vkCmdPipelineBarrier( + GetFrameResources().initCommandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &barrier + ); + submit_inits = true; + initLocker.unlock(); } if (pTexture->desc.BindFlags & BIND_RENDER_TARGET) @@ -5907,7 +5999,7 @@ using namespace Vulkan_Internal; } void GraphicsDevice_Vulkan::SubmitCommandLists() { - transitionLocker.lock(); + initLocker.lock(); VkResult res; // Submit current frame: @@ -5917,25 +6009,10 @@ using namespace Vulkan_Internal; QUEUE_TYPE submit_queue = QUEUE_COUNT; // Transitions: - bool submit_transitions = false; - if(!transitions.empty()) + if(submit_inits) { - vkCmdPipelineBarrier( - frame.transitionCommandBuffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - 0, - 0, nullptr, - 0, nullptr, - (uint32_t)transitions.size(), - transitions.data() - ); - transitions.clear(); - - res = vkEndCommandBuffer(frame.transitionCommandBuffer); + res = vkEndCommandBuffer(frame.initCommandBuffer); assert(res == VK_SUCCESS); - - submit_transitions = true; } uint64_t copy_sync = copyAllocator.flush(); @@ -5980,10 +6057,10 @@ using namespace Vulkan_Internal; copy_sync = 0; } - if (submit_transitions) + if (submit_inits) { - queues[submit_queue].submit_cmds.push_back(frame.transitionCommandBuffer); - submit_transitions = false; + queues[submit_queue].submit_cmds.push_back(frame.initCommandBuffer); + submit_inits = false; } for (auto& swapchain : prev_swapchains[cmd]) @@ -6048,7 +6125,7 @@ using namespace Vulkan_Internal; // Restart transition command buffers: { - res = vkResetCommandPool(device, frame.transitionCommandPool, 0); + res = vkResetCommandPool(device, frame.initCommandPool, 0); assert(res == VK_SUCCESS); VkCommandBufferBeginInfo beginInfo = {}; @@ -6056,11 +6133,13 @@ using namespace Vulkan_Internal; beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; beginInfo.pInheritanceInfo = nullptr; // Optional - res = vkBeginCommandBuffer(frame.transitionCommandBuffer, &beginInfo); + res = vkBeginCommandBuffer(frame.initCommandBuffer, &beginInfo); assert(res == VK_SUCCESS); } } - transitionLocker.unlock(); + + submit_inits = false; + initLocker.unlock(); } void GraphicsDevice_Vulkan::WaitForGPU() const diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index 3890b0973..09ee8c9f4 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -178,8 +178,8 @@ namespace wiGraphics }; mutable CopyAllocator copyAllocator; - mutable std::mutex transitionLocker; - mutable std::vector transitions; + mutable std::mutex initLocker; + mutable bool submit_inits = false; struct FrameResources { @@ -187,8 +187,8 @@ namespace wiGraphics VkCommandPool commandPools[COMMANDLIST_COUNT][QUEUE_COUNT] = {}; VkCommandBuffer commandBuffers[COMMANDLIST_COUNT][QUEUE_COUNT] = {}; - VkCommandPool transitionCommandPool = VK_NULL_HANDLE; - VkCommandBuffer transitionCommandBuffer = VK_NULL_HANDLE; + VkCommandPool initCommandPool = VK_NULL_HANDLE; + VkCommandBuffer initCommandBuffer = VK_NULL_HANDLE; struct DescriptorBinder { diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index f9f23fa9a..b1eed25e5 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -8214,6 +8214,14 @@ void ComputeShadingRateClassification( if (GetVariableRateShadingClassificationDebug()) { device->BindUAV(CS, &debugUAV, 1, cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Image(&debugUAV, debugUAV.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + device->BindComputeShader(&shaders[CSTYPE_SHADINGRATECLASSIFICATION_DEBUG], cmd); } else @@ -8261,6 +8269,16 @@ void ComputeShadingRateClassification( device->Barrier(barriers, arraysize(barriers), cmd); } + if (GetVariableRateShadingClassificationDebug()) + { + { + GPUBarrier barriers[] = { + GPUBarrier::Image(&debugUAV, IMAGE_LAYOUT_UNORDERED_ACCESS, debugUAV.desc.layout), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + } + device->UnbindUAVs(0, arraysize(uavs), cmd); wiProfiler::EndRange(range); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index e70f84ba2..1e5108721 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates, breaking compatibility changes const int minor = 56; // minor bug fixes, alterations, refactors, updates - const int revision = 75; + const int revision = 76; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);