From 29efc741f1ff7b1c487a2c06e80c6fb4df89c19c Mon Sep 17 00:00:00 2001 From: Honeybunch Date: Fri, 15 Nov 2024 14:05:28 -0800 Subject: [PATCH] Adding an image load failure case to the shader debug zoo and implementing a fix --- .../driver/shaders/spirv/spirv_debug.cpp | 8 ++ renderdoc/driver/shaders/spirv/spirv_debug.h | 3 + renderdoc/driver/vulkan/vk_shaderdebug.cpp | 130 ++++++++++++++++++ util/test/demos/vk/vk_shader_debug_zoo.cpp | 53 ++++--- 4 files changed, 174 insertions(+), 20 deletions(-) diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.cpp b/renderdoc/driver/shaders/spirv/spirv_debug.cpp index f446e53f082..4e1299e4f0c 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug.cpp @@ -2840,6 +2840,14 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray set0001(result); } } + else if(texType & DebugAPIWrapper::Buffer_Texture) + { + if(!debugger.GetAPIWrapper()->ReadTexelBuffer(img.GetBindIndex(), coord, result)) + { + // sample failed. Pretend we got 0 columns back + set0001(result); + } + } else { if(!debugger.GetAPIWrapper()->ReadTexel(img.GetBindIndex(), coord, diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.h b/renderdoc/driver/shaders/spirv/spirv_debug.h index 8d6b4b73673..2954d0d173a 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.h +++ b/renderdoc/driver/shaders/spirv/spirv_debug.h @@ -69,6 +69,9 @@ class DebugAPIWrapper virtual bool WriteTexel(ShaderBindIndex imageBind, const ShaderVariable &coord, uint32_t sample, const ShaderVariable &value) = 0; + virtual bool ReadTexelBuffer(ShaderBindIndex bind, const ShaderVariable &coord, + ShaderVariable &output) = 0; + virtual void FillInputValue(ShaderVariable &var, ShaderBuiltin builtin, uint32_t location, uint32_t component) = 0; diff --git a/renderdoc/driver/vulkan/vk_shaderdebug.cpp b/renderdoc/driver/vulkan/vk_shaderdebug.cpp index 01257a26967..59a54d81d23 100644 --- a/renderdoc/driver/vulkan/vk_shaderdebug.cpp +++ b/renderdoc/driver/vulkan/vk_shaderdebug.cpp @@ -493,6 +493,91 @@ class VulkanAPIWrapper : public rdcspv::DebugAPIWrapper return true; } + virtual bool ReadTexelBuffer(ShaderBindIndex bind, const ShaderVariable &coord, + ShaderVariable &output) override + { + const TexelBufData &data = PopulateTexelBuffer(bind); + + uint32_t index = uintComp(coord, 0); + uint64_t offset = index * data.texelSize; + + if(offset + data.texelSize > data.bytes.size()) + { + m_pDriver->AddDebugMessage( + MessageCategory::Execution, MessageSeverity::High, MessageSource::RuntimeWarning, + StringFormat::Fmt("Out of bounds access to buffer, index %u outside size of %u", index, + data.bytes.size() / data.texelSize)); + return false; + } + + CompType varComp = VarTypeCompType(output.type); + + set0001(output); + + ShaderVariable input; + input.columns = data.fmt.compCount; + + if(data.fmt.compType == CompType::UInt) + { + RDCASSERT(varComp == CompType::UInt, varComp); + + // set up input type for proper expansion below + if(data.fmt.compByteWidth == 1) + input.type = VarType::UByte; + else if(data.fmt.compByteWidth == 2) + input.type = VarType::UShort; + else if(data.fmt.compByteWidth == 4) + input.type = VarType::UInt; + else if(data.fmt.compByteWidth == 8) + input.type = VarType::ULong; + + memcpy(input.value.u8v.data(), data.bytes.data() + offset, data.texelSize); + + for(uint8_t c = 0; c < RDCMIN(output.columns, input.columns); c++) + setUintComp(output, c, uintComp(input, c)); + } + else if(data.fmt.compType == CompType::SInt) + { + RDCASSERT(varComp == CompType::SInt, varComp); + + // set up input type for proper expansion below + if(data.fmt.compByteWidth == 1) + input.type = VarType::SByte; + else if(data.fmt.compByteWidth == 2) + input.type = VarType::SShort; + else if(data.fmt.compByteWidth == 4) + input.type = VarType::SInt; + else if(data.fmt.compByteWidth == 8) + input.type = VarType::SLong; + + memcpy(input.value.u8v.data(), data.bytes.data() + offset, data.texelSize); + + for(uint8_t c = 0; c < RDCMIN(output.columns, input.columns); c++) + setIntComp(output, c, intComp(input, c)); + } + else + { + RDCASSERT(varComp == CompType::Float, varComp); + + // do the decode of whatever unorm/float/etc the format is + FloatVector v = DecodeFormattedComponents(data.fmt, data.bytes.data() + offset); + + // set it into f32v + input.value.f32v[0] = v.x; + input.value.f32v[1] = v.y; + input.value.f32v[2] = v.z; + input.value.f32v[3] = v.w; + + // read as floats + input.type = VarType::Float; + + for(uint8_t c = 0; c < RDCMIN(output.columns, input.columns); c++) + setFloatComp(output, c, input.value.f32v[c]); + } + + return true; + } + virtual void FillInputValue(ShaderVariable &var, ShaderBuiltin builtin, uint32_t location, uint32_t component) override { @@ -1526,7 +1611,15 @@ class VulkanAPIWrapper : public rdcspv::DebugAPIWrapper } }; + struct TexelBufData + { + uint32_t texelSize = 0; + ResourceFormat fmt; + bytebuf bytes; + }; + std::map imageCache; + std::map texelBufCache; const Descriptor &GetDescriptor(const rdcstr &access, ShaderBindIndex index, bool &valid) { @@ -1766,6 +1859,43 @@ class VulkanAPIWrapper : public rdcspv::DebugAPIWrapper return data; } + TexelBufData &PopulateTexelBuffer(ShaderBindIndex bind) + { + auto insertIt = texelBufCache.insert(std::make_pair(bind, TexelBufData())); + TexelBufData &data = insertIt.first->second; + if(insertIt.second) + { + bool valid = true; + const Descriptor &bufData = GetDescriptor("accessing texel buffer value", bind, valid); + if(valid) + { + // if the resources might be dirty from side-effects from the action, replay back to right + // before it. + if(m_ResourcesDirty) + { + VkMarkerRegion region("un-dirtying resources"); + m_pDriver->ReplayLog(0, m_EventID, eReplay_WithoutDraw); + m_ResourcesDirty = false; + } + + if(bufData.resource != ResourceId()) + { + const VulkanCreationInfo::BufferView &viewProps = + m_Creation.m_BufferView[m_pDriver->GetResourceManager()->GetLiveID(bufData.view)]; + + data.fmt = MakeResourceFormat(viewProps.format); + data.texelSize = (uint32_t)GetByteSize(1, 1, 1, viewProps.format, 0); + + m_pDriver->GetReplay()->GetBufferData( + m_pDriver->GetResourceManager()->GetLiveID(bufData.resource), bufData.byteOffset, + bufData.byteSize, data.bytes); + } + } + } + + return data; + } + VkPipeline MakePipe(const ShaderConstParameters ¶ms, uint32_t floatBitSize, bool depthTex, bool uintTex, bool sintTex) { diff --git a/util/test/demos/vk/vk_shader_debug_zoo.cpp b/util/test/demos/vk/vk_shader_debug_zoo.cpp index 69334443f8d..235b655959c 100644 --- a/util/test/demos/vk/vk_shader_debug_zoo.cpp +++ b/util/test/demos/vk/vk_shader_debug_zoo.cpp @@ -167,21 +167,23 @@ layout(set = 0, binding = 16, rgba32f) uniform coherent image2D storeImage; layout(set = 0, binding = 17) uniform samplerBuffer texBuffer; layout(set = 0, binding = 18, rgba32f) uniform coherent imageBuffer storeTexBuffer; -layout(set = 0, binding = 19) uniform sampler shadowSampler; +layout(set = 0, binding = 19, rgba8ui) uniform coherent uimageBuffer storeTexBufferUint; -layout(set = 0, binding = 20) uniform samplerCube cubeSampler; +layout(set = 0, binding = 20) uniform sampler shadowSampler; -layout(set = 0, binding = 21, std430) buffer atomicbuftype +layout(set = 0, binding = 21) uniform samplerCube cubeSampler; + +layout(set = 0, binding = 22, std430) buffer atomicbuftype { uvec4 data[]; } atomicbuf; -layout(set = 0, r32ui, binding = 22) uniform uimage2D atomicimg; +layout(set = 0, r32ui, binding = 23) uniform uimage2D atomicimg; -layout(set = 0, binding = 30) uniform sampler2DArray queryTest; -layout(set = 0, binding = 31) uniform sampler2DMSArray queryTestMS; +layout(set = 0, binding = 31) uniform sampler2DArray queryTest; +layout(set = 0, binding = 32) uniform sampler2DMSArray queryTestMS; -layout(set = 0, binding = 32) uniform texture2D depthImage; +layout(set = 0, binding = 33) uniform texture2D depthImage; #if TEST_DESC_INDEXING @@ -1576,6 +1578,11 @@ void main() Color += vec4(1.0, 1.0, 1.0, 1.0); break; } + case 177: + { + Color = vec4(imageLoad(storeTexBufferUint, int(zeroi+2)).x, 1, 0, 1); + break; + } default: break; } } @@ -4111,13 +4118,14 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource {16, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, {17, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, {18, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, - {19, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, - {20, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, - {21, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, - {22, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, - {30, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, + {19, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, + {20, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, + {21, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, + {22, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, + {23, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, {31, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, - {32, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, + {32, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, + {33, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, })); std::vector setLayouts = {setlayout0}; @@ -4643,6 +4651,9 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource VkBufferView store_bufview = createBufferView( vkh::BufferViewCreateInfo(store_texbuffer.buffer, VK_FORMAT_R32G32B32A32_SFLOAT)); + VkBufferView store_bufview_uint = + createBufferView(vkh::BufferViewCreateInfo(store_texbuffer.buffer, VK_FORMAT_R8G8B8A8_UINT)); + setName(pointsampler, "pointsampler"); setName(linearsampler, "linearsampler"); setName(mipsampler, "mipsampler"); @@ -4695,27 +4706,29 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource vkh::WriteDescriptorSet(descset0, 17, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, {bufview}), vkh::WriteDescriptorSet(descset0, 18, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, {store_bufview}), + vkh::WriteDescriptorSet(descset0, 19, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + {store_bufview_uint}), vkh::WriteDescriptorSet( - descset0, 19, VK_DESCRIPTOR_TYPE_SAMPLER, + descset0, 20, VK_DESCRIPTOR_TYPE_SAMPLER, {vkh::DescriptorImageInfo(VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED, shadowsampler)}), vkh::WriteDescriptorSet( - descset0, 20, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + descset0, 21, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, {vkh::DescriptorImageInfo(randomcubeview, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, linearsampler)}), - vkh::WriteDescriptorSet(descset0, 21, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + vkh::WriteDescriptorSet(descset0, 22, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, {vkh::DescriptorBufferInfo(atomic_buffer.buffer)}), vkh::WriteDescriptorSet( - descset0, 22, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + descset0, 23, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, {vkh::DescriptorImageInfo(atomic_view, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE)}), vkh::WriteDescriptorSet( - descset0, 30, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + descset0, 31, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, {vkh::DescriptorImageInfo(queryTestView, VK_IMAGE_LAYOUT_GENERAL, mipsampler)}), vkh::WriteDescriptorSet( - descset0, 31, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + descset0, 32, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, {vkh::DescriptorImageInfo(queryTestMSView, VK_IMAGE_LAYOUT_GENERAL, mipsampler)}), vkh::WriteDescriptorSet( - descset0, 32, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + descset0, 33, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, {vkh::DescriptorImageInfo(shadowview, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE)}), });