From 38afb7c8adfd63c78c64cbfa3d003df9e5a5000d Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 14 Mar 2023 16:32:06 +0000 Subject: [PATCH] Fix handling of S8 multisampled textures. Closes #2883 --- renderdoc/data/glsl/glsl_globals.h | 1 + renderdoc/data/glsl/vk_depthbuf2ms.frag | 20 ++ renderdoc/data/glsl/vk_depthms2buffer.comp | 20 ++ renderdoc/driver/vulkan/vk_debug.cpp | 172 +++++++++++++++--- renderdoc/driver/vulkan/vk_debug.h | 14 +- .../driver/vulkan/vk_msaa_buffer_conv.cpp | 93 +++++++--- .../driver/vulkan/wrappers/vk_cmd_funcs.cpp | 27 ++- .../driver/vulkan/wrappers/vk_draw_funcs.cpp | 5 +- util/test/demos/vk/vk_discard_zoo.cpp | 4 + util/test/demos/vk/vk_texture_zoo.cpp | 10 +- 10 files changed, 295 insertions(+), 71 deletions(-) diff --git a/renderdoc/data/glsl/glsl_globals.h b/renderdoc/data/glsl/glsl_globals.h index 98ff8725c..00d67f89d 100644 --- a/renderdoc/data/glsl/glsl_globals.h +++ b/renderdoc/data/glsl/glsl_globals.h @@ -108,6 +108,7 @@ precision highp int; #define SHADER_D24_UNORM_S8_UINT 3 #define SHADER_D32_SFLOAT 4 #define SHADER_D32_SFLOAT_S8_UINT 5 +#define SHADER_S8_UINT 6 // divide MS<->buffer workgroups by 64 #define MS_DISPATCH_LOCAL_SIZE 64 diff --git a/renderdoc/data/glsl/vk_depthbuf2ms.frag b/renderdoc/data/glsl/vk_depthbuf2ms.frag index 79781f6c2..e803636fc 100644 --- a/renderdoc/data/glsl/vk_depthbuf2ms.frag +++ b/renderdoc/data/glsl/vk_depthbuf2ms.frag @@ -102,6 +102,26 @@ void main() uint stencilData = srcData[idx * 2 + 1]; stencil = stencilData & 0xFF; } + else if(format == SHADER_S8_UINT) + { + uint stencilData = srcData[idx / 4]; + if((idx % 4) == 0) + { + stencil = stencilData & 0x000000FF; + } + else if((idx % 4) == 1) + { + stencil = (stencilData & 0x0000FF00) >> 8; + } + else if((idx % 4) == 2) + { + stencil = (stencilData & 0x00FF0000) >> 16; + } + else + { + stencil = (stencilData & 0xFF000000) >> 24; + } + } if(currentStencil < 256u) { diff --git a/renderdoc/data/glsl/vk_depthms2buffer.comp b/renderdoc/data/glsl/vk_depthms2buffer.comp index 993fdf84e..eb0e9d213 100644 --- a/renderdoc/data/glsl/vk_depthms2buffer.comp +++ b/renderdoc/data/glsl/vk_depthms2buffer.comp @@ -115,4 +115,24 @@ void main() result[dispatchOffset + (idx * 2 + 0)] = floatBitsToUint(depth); result[dispatchOffset + (idx * 2 + 1)] = stencil; } + // For S8, we need to sample 4 pixels at a time + else if(format == SHADER_S8_UINT) + { + int pxIdx = int(idx * 4); + int x0 = (pxIdx + 0) % textureWidth; + int y0 = (pxIdx + 0) / textureWidth; + int x1 = (pxIdx + 1) % textureWidth; + int y1 = (pxIdx + 1) / textureWidth; + int x2 = (pxIdx + 2) % textureWidth; + int y2 = (pxIdx + 2) / textureWidth; + int x3 = (pxIdx + 3) % textureWidth; + int y3 = (pxIdx + 3) / textureWidth; + + uvec4 stencil = uvec4(texelFetch(srcStencilMS, ivec3(x0, y0, slice), sampleIdx).x, + texelFetch(srcStencilMS, ivec3(x1, y1, slice), sampleIdx).x, + texelFetch(srcStencilMS, ivec3(x2, y2, slice), sampleIdx).x, + texelFetch(srcStencilMS, ivec3(x3, y3, slice), sampleIdx).x); + result[dispatchOffset + idx] = ((stencil.x & 0xFF) << 0) | ((stencil.y & 0xFF) << 8) | + ((stencil.z & 0xFF) << 16) | ((stencil.w & 0xFF) << 24); + } } diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index 699448597..126e99bc7 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -374,25 +374,6 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver) ////////////////////////////////////////////////////////////////// // Color MS <-> Buffer copy (via compute) - VkDescriptorPoolSize bufferPoolTypes[] = { - {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 2}, - {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, - {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1}, - }; - - VkDescriptorPoolCreateInfo bufferPoolInfo = { - VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - NULL, - 0, - 1, - ARRAY_COUNT(bufferPoolTypes), - &bufferPoolTypes[0], - }; - - vkr = m_pDriver->vkCreateDescriptorPool(dev, &bufferPoolInfo, NULL, &m_BufferMSDescriptorPool); - CheckVkResult(vkr); - - rm->SetInternalResource(GetResID(m_BufferMSDescriptorPool)); CREATE_OBJECT(m_BufferMSDescSetLayout, { @@ -419,12 +400,41 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver) rm->SetInternalResource(GetResID(m_DepthMS2BufferPipe)); rm->SetInternalResource(GetResID(m_Buffer2MSPipe)); - CREATE_OBJECT(m_BufferMSDescSet, m_BufferMSDescriptorPool, m_BufferMSDescSetLayout); - rm->SetInternalResource(GetResID(m_BufferMSDescSet)); - ////////////////////////////////////////////////////////////////// // Depth MS to Buffer copy (via compute) + // need a dummy float formatted texture but that's easy as we can pick something guaranteed by the + // spec + { + VkImageCreateInfo imInfo = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + NULL, + 0, + VK_IMAGE_TYPE_2D, + // format is required to be supported for sampling + VK_FORMAT_R8G8B8A8_UNORM, + {1, 1, 1}, + 1, + 1, + // sampledImageColorSampleCounts must include VK_SAMPLE_COUNT_4_BIT for 2D non-integer + // optimal tiled textures + VK_SAMPLE_COUNT_4_BIT, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_SAMPLED_BIT, + VK_SHARING_MODE_EXCLUSIVE, + 0, + NULL, + VK_IMAGE_LAYOUT_UNDEFINED, + }; + + vkr = driver->vkCreateImage(driver->GetDev(), &imInfo, NULL, &m_DummyDepthImage); + CheckVkResult(vkr); + + NameVulkanObject(m_DummyDepthImage, "m_DummyDepthImage"); + + rm->SetInternalResource(GetResID(m_DummyDepthImage)); + } + // need a dummy UINT texture to fill the binding when we don't have a stencil aspect to copy. // unfortunately there's no single guaranteed UINT format that can be sampled as MSAA, so we try a // few since hopefully we'll find one that will work. @@ -502,24 +512,45 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver) rm->SetInternalResource(GetResID(m_DummyStencilImage)); + VkMemoryRequirements depthmrq = {}; + driver->vkGetImageMemoryRequirements(driver->GetDev(), m_DummyDepthImage, &depthmrq); + VkMemoryRequirements mrq = {}; driver->vkGetImageMemoryRequirements(driver->GetDev(), m_DummyStencilImage, &mrq); + // assume we can combine these images into one allocation + RDCASSERT((mrq.memoryTypeBits & depthmrq.memoryTypeBits) != 0, mrq.memoryTypeBits, + depthmrq.memoryTypeBits); + + // only use memory types that support both + mrq.memoryTypeBits &= depthmrq.memoryTypeBits; + // use worst case alignment + mrq.alignment = RDCMAX(mrq.alignment, depthmrq.alignment); + + // align each size individually (to worst case alignment) + depthmrq.size = AlignUp(depthmrq.size, mrq.alignment); + mrq.size = AlignUp(mrq.size, mrq.alignment); + // allocate memory VkMemoryAllocateInfo allocInfo = { - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, NULL, mrq.size, + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, NULL, depthmrq.size + mrq.size, driver->GetGPULocalMemoryIndex(mrq.memoryTypeBits), }; - vkr = driver->vkAllocateMemory(driver->GetDev(), &allocInfo, NULL, &m_DummyStencilMemory); + vkr = driver->vkAllocateMemory(driver->GetDev(), &allocInfo, NULL, &m_DummyMemory); CheckVkResult(vkr); if(vkr != VK_SUCCESS) return; - rm->SetInternalResource(GetResID(m_DummyStencilMemory)); + rm->SetInternalResource(GetResID(m_DummyMemory)); - vkr = driver->vkBindImageMemory(driver->GetDev(), m_DummyStencilImage, m_DummyStencilMemory, 0); + NameVulkanObject(m_DummyStencilImage, "m_DummyMemory"); + + vkr = driver->vkBindImageMemory(driver->GetDev(), m_DummyStencilImage, m_DummyMemory, 0); + CheckVkResult(vkr); + + vkr = driver->vkBindImageMemory(driver->GetDev(), m_DummyDepthImage, m_DummyMemory, mrq.size); CheckVkResult(vkr); VkImageViewCreateInfo viewInfo = { @@ -543,6 +574,16 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver) rm->SetInternalResource(GetResID(m_DummyStencilView)); + viewInfo.image = m_DummyDepthImage; + viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.format = VK_FORMAT_R8G8B8A8_UNORM; + vkr = driver->vkCreateImageView(driver->GetDev(), &viewInfo, NULL, &m_DummyDepthView); + CheckVkResult(vkr); + + NameVulkanObject(m_DummyDepthView, "m_DummyDepthView"); + + rm->SetInternalResource(GetResID(m_DummyDepthView)); + VkCommandBuffer cmd = driver->GetNextCmd(); if(cmd == VK_NULL_HANDLE) @@ -570,6 +611,10 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver) DoPipelineBarrier(cmd, 1, &barrier); + barrier.image = Unwrap(m_DummyDepthImage); + barrierAspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + DoPipelineBarrier(cmd, 1, &barrier); + ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); break; @@ -583,6 +628,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver) VkFormat formats[] = { VK_FORMAT_D16_UNORM, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, + VK_FORMAT_S8_UINT, }; VkSampleCountFlagBits sampleCounts[] = { @@ -739,11 +785,14 @@ VulkanDebugManager::~VulkanDebugManager() for(uint32_t i = 0; i < VKMeshDisplayPipelines::ePipe_Count; i++) m_pDriver->vkDestroyPipeline(dev, it->second.pipes[i], NULL); - m_pDriver->vkDestroyDescriptorPool(dev, m_BufferMSDescriptorPool, NULL); + for(VkDescriptorPool pool : m_BufferMSDescriptorPools) + m_pDriver->vkDestroyDescriptorPool(dev, pool, NULL); + m_pDriver->vkDestroyImageView(dev, m_DummyDepthView, NULL); + m_pDriver->vkDestroyImage(dev, m_DummyDepthImage, NULL); m_pDriver->vkDestroyImageView(dev, m_DummyStencilView, NULL); m_pDriver->vkDestroyImage(dev, m_DummyStencilImage, NULL); - m_pDriver->vkFreeMemory(dev, m_DummyStencilMemory, NULL); + m_pDriver->vkFreeMemory(dev, m_DummyMemory, NULL); m_pDriver->vkDestroyDescriptorSetLayout(dev, m_BufferMSDescSetLayout, NULL); m_pDriver->vkDestroyPipelineLayout(dev, m_BufferMSPipeLayout, NULL); @@ -1667,6 +1716,68 @@ const WrappedVulkan::DescriptorSetInfo &VulkanDebugManager::GetDescSetInfo(Resou return it->second; } +VkDescriptorSet VulkanDebugManager::GetBufferMSDescSet() +{ + if(m_FreeBufferMSDescriptorSets.empty()) + { + WrappedVulkan *driver = m_pDriver; + VulkanResourceManager *rm = driver->GetResourceManager(); + VkResult vkr = VK_SUCCESS; + VkDevice dev = m_pDriver->GetDev(); + + VkDescriptorPoolSize bufferPoolTypes[] = { + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 2 * BufferMSDescriptorPoolSize}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1 * BufferMSDescriptorPoolSize}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 * BufferMSDescriptorPoolSize}, + }; + + VkDescriptorPoolCreateInfo bufferPoolInfo = { + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + NULL, + 0, + BufferMSDescriptorPoolSize, + ARRAY_COUNT(bufferPoolTypes), + &bufferPoolTypes[0], + }; + + VkDescriptorPool pool; + vkr = m_pDriver->vkCreateDescriptorPool(dev, &bufferPoolInfo, NULL, &pool); + CheckVkResult(vkr); + + rm->SetInternalResource(GetResID(pool)); + + m_BufferMSDescriptorPools.push_back(pool); + + rdcarray setLayouts; + setLayouts.fill(BufferMSDescriptorPoolSize, m_BufferMSDescSetLayout); + + VkDescriptorSetAllocateInfo descSetAllocInfo = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + NULL, + pool, + (uint32_t)setLayouts.size(), + setLayouts.data(), + }; + + m_FreeBufferMSDescriptorSets.resize(BufferMSDescriptorPoolSize); + m_pDriver->vkAllocateDescriptorSets(dev, &descSetAllocInfo, m_FreeBufferMSDescriptorSets.data()); + + for(VkDescriptorSet set : m_FreeBufferMSDescriptorSets) + rm->SetInternalResource(GetResID(set)); + } + + VkDescriptorSet ret = m_FreeBufferMSDescriptorSets.back(); + m_FreeBufferMSDescriptorSets.pop_back(); + m_UsedBufferMSDescriptorSets.push_back(ret); + return ret; +} + +void VulkanDebugManager::ResetBufferMSDescriptorPools() +{ + m_FreeBufferMSDescriptorSets.append(m_UsedBufferMSDescriptorSets); + m_UsedBufferMSDescriptorSets.clear(); +} + void VulkanDebugManager::GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, bytebuf &ret) { VkDevice dev = m_pDriver->GetDev(); @@ -1847,7 +1958,7 @@ void VulkanDebugManager::FillWithDiscardPattern(VkCommandBuffer cmd, DiscardType VkMarkerRegion marker( cmd, StringFormat::Fmt("FillWithDiscardPattern %s", ToStr(GetResID(image)).c_str())); - VkImageAspectFlags imAspects = FormatImageAspects(imInfo.format); + const VkImageAspectFlags imAspects = FormatImageAspects(imInfo.format); VkImageSubresourceRange barrierDiscardRange = discardRange; barrierDiscardRange.aspectMask = imAspects; @@ -2049,7 +2160,8 @@ void VulkanDebugManager::FillWithDiscardPattern(VkCommandBuffer cmd, DiscardType &pass); uint32_t offset = 0; - if(imAspects != discardRange.aspectMask) + if(imAspects != discardRange.aspectMask && + imAspects == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { // if we're only discarding one of depth or stencil in a depth/stencil image, pick a // framebuffer that only targets that aspect. diff --git a/renderdoc/driver/vulkan/vk_debug.h b/renderdoc/driver/vulkan/vk_debug.h index 57b6c9a96..bde1bd11b 100644 --- a/renderdoc/driver/vulkan/vk_debug.h +++ b/renderdoc/driver/vulkan/vk_debug.h @@ -124,21 +124,27 @@ private: std::map m_CachedMeshPipelines; // CopyBufferToTex2DMS - VkDescriptorPool m_BufferMSDescriptorPool; VkDescriptorSetLayout m_BufferMSDescSetLayout = VK_NULL_HANDLE; VkPipelineLayout m_BufferMSPipeLayout = VK_NULL_HANDLE; - VkDescriptorSet m_BufferMSDescSet = VK_NULL_HANDLE; + static const uint32_t BufferMSDescriptorPoolSize = 64; + rdcarray m_BufferMSDescriptorPools; + rdcarray m_FreeBufferMSDescriptorSets; + rdcarray m_UsedBufferMSDescriptorSets; + VkDescriptorSet GetBufferMSDescSet(); + void ResetBufferMSDescriptorPools(); VkPipeline m_Buffer2MSPipe = VK_NULL_HANDLE; VkPipeline m_MS2BufferPipe = VK_NULL_HANDLE; VkPipeline m_DepthMS2BufferPipe = VK_NULL_HANDLE; // MSAA dummy images - VkDeviceMemory m_DummyStencilMemory = VK_NULL_HANDLE; + VkDeviceMemory m_DummyMemory = VK_NULL_HANDLE; + VkImage m_DummyDepthImage = {VK_NULL_HANDLE}; + VkImageView m_DummyDepthView = {VK_NULL_HANDLE}; VkImage m_DummyStencilImage = {VK_NULL_HANDLE}; VkImageView m_DummyStencilView = {VK_NULL_HANDLE}; // one per depth/stencil output format, per sample count - VkPipeline m_DepthArray2MSPipe[6][4] = {{VK_NULL_HANDLE}}; + VkPipeline m_DepthArray2MSPipe[7][4] = {{VK_NULL_HANDLE}}; VkPipelineCache m_PipelineCache = VK_NULL_HANDLE; diff --git a/renderdoc/driver/vulkan/vk_msaa_buffer_conv.cpp b/renderdoc/driver/vulkan/vk_msaa_buffer_conv.cpp index 62eec8745..fd4dd9abb 100644 --- a/renderdoc/driver/vulkan/vk_msaa_buffer_conv.cpp +++ b/renderdoc/driver/vulkan/vk_msaa_buffer_conv.cpp @@ -117,18 +117,20 @@ void VulkanDebugManager::CopyTex2DMSToBuffer(VkBuffer destBuffer, VkImage srcMS, destdesc.offset = 0; destdesc.range = VK_WHOLE_SIZE; + VkDescriptorSet descSet = GetBufferMSDescSet(); + VkWriteDescriptorSet writeSet[] = { - {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_BufferMSDescSet), 0, 0, 1, + {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(descSet), 0, 0, 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &srcdesc, NULL, NULL}, - {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_BufferMSDescSet), 2, 0, 1, + {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(descSet), 2, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, NULL, &destdesc, NULL}, }; ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), ARRAY_COUNT(writeSet), writeSet, 0, NULL); ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, - Unwrap(m_BufferMSPipeLayout), 0, 1, - UnwrapPtr(m_BufferMSDescSet), 0, NULL); + Unwrap(m_BufferMSPipeLayout), 0, 1, UnwrapPtr(descSet), 0, + NULL); for(uint32_t currentSlice = baseSlice; currentSlice < numSlices + baseSlice; currentSlice++) { @@ -168,6 +170,7 @@ void VulkanDebugManager::CopyTex2DMSToBuffer(VkBuffer destBuffer, VkImage srcMS, RDCASSERT(cmd == VK_NULL_HANDLE); ObjDisp(dev)->DestroyImageView(Unwrap(dev), srcView, NULL); + ResetBufferMSDescriptorPools(); } void VulkanDebugManager::CopyDepthTex2DMSToBuffer(VkBuffer destBuffer, VkImage srcMS, @@ -197,6 +200,10 @@ void VulkanDebugManager::CopyDepthTex2DMSToBuffer(VkBuffer destBuffer, VkImage s fmtIndex = SHADER_D32_SFLOAT_S8_UINT; aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT; break; + case VK_FORMAT_S8_UINT: + fmtIndex = SHADER_S8_UINT; + aspectFlags = VK_IMAGE_ASPECT_STENCIL_BIT; + break; default: RDCERR("Unexpected depth format: %d", fmt); return; } @@ -220,9 +227,12 @@ void VulkanDebugManager::CopyDepthTex2DMSToBuffer(VkBuffer destBuffer, VkImage s }, }; - vkr = ObjDisp(dev)->CreateImageView(Unwrap(dev), &viewInfo, NULL, &srcDepthView); - CheckVkResult(vkr); - NameUnwrappedVulkanObject(srcDepthView, "Depth MS -> Array srcDepthView"); + if(aspectFlags & VK_IMAGE_ASPECT_DEPTH_BIT) + { + vkr = ObjDisp(dev)->CreateImageView(Unwrap(dev), &viewInfo, NULL, &srcDepthView); + CheckVkResult(vkr); + NameUnwrappedVulkanObject(srcDepthView, "Depth MS -> Array srcDepthView"); + } if(aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT) { @@ -254,6 +264,21 @@ void VulkanDebugManager::CopyDepthTex2DMSToBuffer(VkBuffer destBuffer, VkImage s srcdesc[1].imageView = srcStencilView; srcdesc[1].sampler = VK_NULL_HANDLE; // not used - we use texelFetch + if((aspectFlags & VK_IMAGE_ASPECT_DEPTH_BIT) == 0) + { + if(m_DummyDepthView != VK_NULL_HANDLE) + { + srcdesc[0].imageView = Unwrap(m_DummyDepthView); + } + else + { + // as a last fallback, hope that setting an incompatible view (float not int) will not break + // too badly. This only gets hit when the implementation has such poor format support that + // there are no float formats that can be sampled as MSAA. + srcdesc[0].imageView = srcStencilView; + } + } + if((aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT) == 0) { if(m_DummyStencilView != VK_NULL_HANDLE) @@ -277,27 +302,30 @@ void VulkanDebugManager::CopyDepthTex2DMSToBuffer(VkBuffer destBuffer, VkImage s destdesc.offset = 0; destdesc.range = VK_WHOLE_SIZE; + VkDescriptorSet descSet = GetBufferMSDescSet(); + VkWriteDescriptorSet writeSet[] = { - {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_BufferMSDescSet), 0, 0, 1, + {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(descSet), 0, 0, 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &srcdesc[0], NULL, NULL}, - {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_BufferMSDescSet), 1, 0, 1, + {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(descSet), 1, 0, 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &srcdesc[1], NULL, NULL}, - {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_BufferMSDescSet), 2, 0, 1, + {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(descSet), 2, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, NULL, &destdesc, NULL}, }; ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), ARRAY_COUNT(writeSet), writeSet, 0, NULL); ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, - Unwrap(m_BufferMSPipeLayout), 0, 1, - UnwrapPtr(m_BufferMSDescSet), 0, NULL); + Unwrap(m_BufferMSPipeLayout), 0, 1, UnwrapPtr(descSet), 0, + NULL); for(uint32_t currentSlice = baseSlice; currentSlice < numSlices + baseSlice; currentSlice++) { for(uint32_t currentSample = baseSample; currentSample < numSamples + baseSample; currentSample++) { - // for D16 textures, we need to multisample. - const uint32_t msDivider = fmt == VK_FORMAT_D16_UNORM ? 2 : 1; + // for D16 and S8 textures, we need to multisample. + const uint32_t msDivider = + (fmt == VK_FORMAT_D16_UNORM) ? 2 : (fmt == VK_FORMAT_S8_UINT) ? 4 : 1; const uint32_t workGroupDivider = MS_DISPATCH_LOCAL_SIZE * msDivider; const uint32_t numWorkGroup = AlignUp(extent.width * extent.height, workGroupDivider) / workGroupDivider; @@ -326,9 +354,11 @@ void VulkanDebugManager::CopyDepthTex2DMSToBuffer(VkBuffer destBuffer, VkImage s RDCASSERT(cmd == VK_NULL_HANDLE); - ObjDisp(dev)->DestroyImageView(Unwrap(dev), srcDepthView, NULL); + if(srcDepthView != VK_NULL_HANDLE) + ObjDisp(dev)->DestroyImageView(Unwrap(dev), srcDepthView, NULL); if(srcStencilView != VK_NULL_HANDLE) ObjDisp(dev)->DestroyImageView(Unwrap(dev), srcStencilView, NULL); + ResetBufferMSDescriptorPools(); } void VulkanDebugManager::CopyBufferToTex2DMS(VkCommandBuffer cmd, VkImage destMS, @@ -407,6 +437,8 @@ void VulkanDebugManager::CopyBufferToTex2DMS(VkCommandBuffer cmd, VkImage destMS if(cmd == VK_NULL_HANDLE) return; + VkDescriptorSet descSet = GetBufferMSDescSet(); + { VkMarkerRegion region(cmd, "CopyBufferToTex2DMS"); @@ -428,17 +460,17 @@ void VulkanDebugManager::CopyBufferToTex2DMS(VkCommandBuffer cmd, VkImage destMS destdesc.sampler = VK_NULL_HANDLE; VkWriteDescriptorSet writeSet[] = { - {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_BufferMSDescSet), 2, 0, 1, + {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(descSet), 2, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, NULL, &srcdesc, NULL}, - {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_BufferMSDescSet), 3, 0, 1, + {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(descSet), 3, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &destdesc, NULL, NULL}, }; ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), ARRAY_COUNT(writeSet), writeSet, 0, NULL); ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, - Unwrap(m_BufferMSPipeLayout), 0, 1, - UnwrapPtr(m_BufferMSDescSet), 0, NULL); + Unwrap(m_BufferMSPipeLayout), 0, 1, UnwrapPtr(descSet), 0, + NULL); for(uint32_t currentSlice = 0; currentSlice < numSlices; currentSlice++) { @@ -468,8 +500,10 @@ void VulkanDebugManager::CopyBufferToTex2DMS(VkCommandBuffer cmd, VkImage destMS if(endCommand) ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); - m_pDriver->AddPendingObjectCleanup( - [dev, destView]() { ObjDisp(dev)->DestroyImageView(Unwrap(dev), destView, NULL); }); + m_pDriver->AddPendingObjectCleanup([this, dev, destView]() { + ObjDisp(dev)->DestroyImageView(Unwrap(dev), destView, NULL); + ResetBufferMSDescriptorPools(); + }); } void VulkanDebugManager::CopyDepthBufferToTex2DMS(VkCommandBuffer cmd, VkImage destMS, @@ -510,6 +544,11 @@ void VulkanDebugManager::CopyDepthBufferToTex2DMS(VkCommandBuffer cmd, VkImage d aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT; formatIndex = SHADER_D32_SFLOAT_S8_UINT; break; + case VK_FORMAT_S8_UINT: + pipeIndex = 6; + aspectFlags = VK_IMAGE_ASPECT_STENCIL_BIT; + formatIndex = SHADER_S8_UINT; + break; default: RDCERR("Unexpected depth format: %d", fmt); return; } @@ -563,8 +602,10 @@ void VulkanDebugManager::CopyDepthBufferToTex2DMS(VkCommandBuffer cmd, VkImage d NameUnwrappedVulkanObject(destView[i], "Depth Array -> MS destView[i]"); } + VkDescriptorSet descSet = GetBufferMSDescSet(); + VkWriteDescriptorSet writeSet[] = { - {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_BufferMSDescSet), 2, 0, 1, + {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(descSet), 2, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, NULL, &srcdesc, NULL}, }; @@ -672,8 +713,8 @@ void VulkanDebugManager::CopyDepthBufferToTex2DMS(VkCommandBuffer cmd, VkImage d ObjDisp(cmd)->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE); ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, - Unwrap(m_BufferMSPipeLayout), 0, 1, - UnwrapPtr(m_BufferMSDescSet), 0, NULL); + Unwrap(m_BufferMSPipeLayout), 0, 1, UnwrapPtr(descSet), 0, + NULL); VkViewport viewport = {0.0f, 0.0f, (float)extent.width, (float)extent.height, 0.0f, 1.0f}; ObjDisp(cmd)->CmdSetViewport(Unwrap(cmd), 0, 1, &viewport); @@ -697,12 +738,14 @@ void VulkanDebugManager::CopyDepthBufferToTex2DMS(VkCommandBuffer cmd, VkImage d if(endCommand) ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); - m_pDriver->AddPendingObjectCleanup([dev, fb, rp, destView]() { + m_pDriver->AddPendingObjectCleanup([this, dev, fb, rp, destView]() { for(uint32_t i = 0; i < fb.size(); i++) ObjDisp(dev)->DestroyFramebuffer(Unwrap(dev), fb[i], NULL); ObjDisp(dev)->DestroyRenderPass(Unwrap(dev), rp, NULL); for(uint32_t i = 0; i < destView.size(); i++) ObjDisp(dev)->DestroyImageView(Unwrap(dev), destView[i], NULL); + + ResetBufferMSDescriptorPools(); }); } diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index 3aec55930..6c150c6a1 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -746,12 +746,12 @@ void WrappedVulkan::ApplyRPLoadDiscards(VkCommandBuffer commandBuffer, VkRect2D VkImageSubresourceRange range = viewInfo.range; range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if(depthDontCareLoad) + if(depthDontCareLoad && (viewInfo.range.aspectMask & range.aspectMask) != 0) GetDebugManager()->FillWithDiscardPattern(commandBuffer, DiscardType::RenderPassLoad, image, initialLayout, range, renderArea); range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - if(stencilDontCareLoad) + if(stencilDontCareLoad && (viewInfo.range.aspectMask & range.aspectMask) != 0) GetDebugManager()->FillWithDiscardPattern(commandBuffer, DiscardType::RenderPassLoad, image, initialLayout, range, renderArea); } @@ -2295,13 +2295,13 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass(SerialiserType &ser, VkCommandB VkImageSubresourceRange range = viewInfo.range; range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if(depthDontCareStore) + if(depthDontCareStore && (viewInfo.range.aspectMask & range.aspectMask) != 0) GetDebugManager()->FillWithDiscardPattern( commandBuffer, DiscardType::RenderPassStore, image, rpinfo.attachments[i].finalLayout, range, renderArea); range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - if(stencilDontCareStore) + if(stencilDontCareStore && (viewInfo.range.aspectMask & range.aspectMask) != 0) GetDebugManager()->FillWithDiscardPattern( commandBuffer, DiscardType::RenderPassStore, image, rpinfo.attachments[i].finalLayout, range, renderArea); @@ -6942,14 +6942,20 @@ bool WrappedVulkan::Serialise_vkCmdBeginRendering(SerialiserType &ser, VkCommand (RenderingInfo.flags & VK_RENDERING_RESUMING_BIT) == 0) { rdcarray dynAtts = renderstate.dynamicRendering.color; - dynAtts.push_back(renderstate.dynamicRendering.depth); - size_t depthIdx = dynAtts.size() - 1; + size_t depthIdx = ~0U; size_t stencilIdx = ~0U; VkImageAspectFlags depthAspects = VK_IMAGE_ASPECT_DEPTH_BIT; + if(renderstate.dynamicRendering.depth.imageView != VK_NULL_HANDLE) + { + dynAtts.push_back(renderstate.dynamicRendering.depth); + depthIdx = dynAtts.size() - 1; + } + // if we have different images attached, or different store ops, treat stencil separately - if(renderstate.dynamicRendering.stencil.imageView != VK_NULL_HANDLE && + if(renderstate.dynamicRendering.depth.imageView != VK_NULL_HANDLE && + renderstate.dynamicRendering.stencil.imageView != VK_NULL_HANDLE && (renderstate.dynamicRendering.depth.imageView != renderstate.dynamicRendering.stencil.imageView || renderstate.dynamicRendering.depth.loadOp != @@ -6962,6 +6968,12 @@ bool WrappedVulkan::Serialise_vkCmdBeginRendering(SerialiserType &ser, VkCommand else if(renderstate.dynamicRendering.stencil.imageView != VK_NULL_HANDLE) { depthAspects |= VK_IMAGE_ASPECT_STENCIL_BIT; + + if(renderstate.dynamicRendering.depth.imageView == VK_NULL_HANDLE) + { + dynAtts.push_back(renderstate.dynamicRendering.stencil); + stencilIdx = dynAtts.size() - 1; + } } for(size_t i = 0; i < dynAtts.size(); i++) @@ -6980,6 +6992,7 @@ bool WrappedVulkan::Serialise_vkCmdBeginRendering(SerialiserType &ser, VkCommand if(i == depthIdx) range.aspectMask = depthAspects; + // if this is a stencil-only attachment this will override depthAspects if(i == stencilIdx) range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; diff --git a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp index 7b7efb168..1ee6d6925 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp @@ -2542,7 +2542,7 @@ bool WrappedVulkan::Serialise_vkCmdClearAttachments(SerialiserType &ser, { if(pAttachments[a].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) action.flags |= ActionFlags::ClearColor; - if(pAttachments[a].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) + if(pAttachments[a].aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) action.flags |= ActionFlags::ClearDepthStencil; } @@ -2575,7 +2575,8 @@ bool WrappedVulkan::Serialise_vkCmdClearAttachments(SerialiserType &ser, } } } - else if(pAttachments[a].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) + else if(pAttachments[a].aspectMask & + (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { if(rp.subpasses[state.subpass].depthstencilAttachment >= 0) { diff --git a/util/test/demos/vk/vk_discard_zoo.cpp b/util/test/demos/vk/vk_discard_zoo.cpp index 627db4ca0..ef7fc9078 100644 --- a/util/test/demos/vk/vk_discard_zoo.cpp +++ b/util/test/demos/vk/vk_discard_zoo.cpp @@ -551,6 +551,10 @@ void main() DiscardImage(cmd, tex); TEX_TEST("DiscardAll", MakeTex2D(VK_FORMAT_S8_UINT, 300, 300, 5, 4)); DiscardImage(cmd, tex); + TEX_TEST("DiscardAll", MakeTex2DMS(VK_FORMAT_S8_UINT, 300, 300, 4)); + DiscardImage(cmd, tex); + TEX_TEST("DiscardAll", MakeTex2DMS(VK_FORMAT_S8_UINT, 300, 300, 4, 2)); + DiscardImage(cmd, tex); } TEX_TEST("DiscardAll", MakeTex2D(depthFormat, 300, 300, 5)); diff --git a/util/test/demos/vk/vk_texture_zoo.cpp b/util/test/demos/vk/vk_texture_zoo.cpp index aa11b9948..b49b7f636 100644 --- a/util/test/demos/vk/vk_texture_zoo.cpp +++ b/util/test/demos/vk/vk_texture_zoo.cpp @@ -1068,6 +1068,8 @@ void main() TEST_CASE(TextureType::Unknown, VK_FORMAT_D16_UNORM, VK_FORMAT_D16_UNORM, 0, 0, DataType::Float), + + TEST_CASE(TextureType::Unknown, VK_FORMAT_S8_UINT, VK_FORMAT_S8_UINT, 0, 0, DataType::UInt), }; for(VKFormat f : depth_tests) @@ -1121,9 +1123,11 @@ void main() { aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if(t.fmt.viewFmt == VK_FORMAT_S8_UINT || t.fmt.viewFmt == VK_FORMAT_D16_UNORM_S8_UINT || - t.fmt.viewFmt == VK_FORMAT_D24_UNORM_S8_UINT || - t.fmt.viewFmt == VK_FORMAT_D32_SFLOAT_S8_UINT) + if(t.fmt.viewFmt == VK_FORMAT_S8_UINT) + aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + else if(t.fmt.viewFmt == VK_FORMAT_D16_UNORM_S8_UINT || + t.fmt.viewFmt == VK_FORMAT_D24_UNORM_S8_UINT || + t.fmt.viewFmt == VK_FORMAT_D32_SFLOAT_S8_UINT) aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; }