diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index 825953e3f..f9f296b53 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -3278,7 +3278,8 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo int index = 0; // we pick RGBA8 formats to be guaranteed they will be supported - VkFormat formats[] = {VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_SINT}; + VkFormat formats[] = {VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UINT, + VK_FORMAT_R8G8B8A8_SINT, VK_FORMAT_D16_UNORM}; VkImageType types[] = {VK_IMAGE_TYPE_1D, VK_IMAGE_TYPE_2D, VK_IMAGE_TYPE_3D, VK_IMAGE_TYPE_2D}; VkImageViewType viewtypes[] = { VK_IMAGE_VIEW_TYPE_1D_ARRAY, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_VIEW_TYPE_3D, @@ -3311,6 +3312,10 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo { for(size_t type = 0; type < ARRAY_COUNT(types); type++) { + // don't create 3D depth + if(formats[fmt] == VK_FORMAT_D16_UNORM && types[type] == VK_IMAGE_TYPE_3D) + continue; + // create 1x1 image of the right size VkImageCreateInfo imInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, @@ -3330,8 +3335,8 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo VK_IMAGE_LAYOUT_UNDEFINED, }; - // make the 2D image cube-compatible - if(type == 1) + // make the 2D image cube-compatible for non-depth + if(type == 1 && formats[fmt] != VK_FORMAT_D16_UNORM) { imInfo.arrayLayers = 6; imInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; @@ -3353,6 +3358,10 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo alloc.offs); driver->CheckVkResult(vkr); + // don't add dummy writes/infos for depth, we just want the images and views + if(formats[fmt] == VK_FORMAT_D16_UNORM) + continue; + // fill out the descriptor set write to the write binding - set will be filled out // on demand when we're actually using these writes. DummyWrites[index].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -3395,6 +3404,8 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo DummyInfos[index + 1].sampler = Unwrap(DummySampler); DummyInfos[index + 1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + RDCASSERT(index + 1 < (int)ARRAY_COUNT(DummyInfos)); + // align up for the dummy buffer { VkBufferCreateInfo bufInfo = { @@ -3433,6 +3444,10 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo cube = true; } + // don't create 3D depth or cubes + if(formats[fmt] == VK_FORMAT_D16_UNORM && (viewtypes[type] == VK_IMAGE_VIEW_TYPE_3D || cube)) + continue; + VkImageViewCreateInfo viewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, NULL, @@ -3447,6 +3462,9 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo }, }; + if(formats[fmt] == VK_FORMAT_D16_UNORM) + viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if(cube) viewInfo.subresourceRange.layerCount = 6; @@ -3461,10 +3479,6 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo if(cube) continue; - RDCASSERT((size_t)index < ARRAY_COUNT(DummyInfos), index); - - DummyInfos[index].imageView = Unwrap(DummyImageViews[fmt][type]); - // need to update image layout into valid state VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -3479,8 +3493,18 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo {VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}, }; + if(formats[fmt] == VK_FORMAT_D16_UNORM) + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + DoPipelineBarrier(cmd, 1, &barrier); + if(formats[fmt] == VK_FORMAT_D16_UNORM) + continue; + + RDCASSERT((size_t)index < ARRAY_COUNT(DummyInfos), index); + + DummyInfos[index].imageView = Unwrap(DummyImageViews[fmt][type]); + index++; } } @@ -3489,6 +3513,8 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo DummyInfos[index].imageView = DummyInfos[1].imageView; DummyInfos[index + 1].imageView = DummyInfos[1].imageView; + RDCASSERT(index + 1 < (int)ARRAY_COUNT(DummyInfos)); + if(DummyBuffer != VK_NULL_HANDLE) { VkFormat bufViewTypes[] = { diff --git a/renderdoc/driver/vulkan/vk_replay.h b/renderdoc/driver/vulkan/vk_replay.h index 4e358d418..a94560f17 100644 --- a/renderdoc/driver/vulkan/vk_replay.h +++ b/renderdoc/driver/vulkan/vk_replay.h @@ -246,10 +246,10 @@ struct ShaderDebugData VkFramebuffer Framebuffer = VK_NULL_HANDLE; VkRenderPass RenderPass = VK_NULL_HANDLE; - VkDescriptorImageInfo DummyImageInfos[3][6] = {}; - VkWriteDescriptorSet DummyWrites[3][7] = {}; + VkDescriptorImageInfo DummyImageInfos[4][6] = {}; + VkWriteDescriptorSet DummyWrites[4][7] = {}; - VkShaderModule Module[6] = {}; + VkShaderModule Module[7] = {}; std::map m_Pipelines; @@ -590,16 +590,16 @@ private: // images and views are re-used elsewhere in replay, so index them sensibly // - // [float/uint/sint][1D/2D/3D/MS/Cube] + // [float/uint/sint/depth][1D/2D/3D/MS/Cube] // // the cube image is re-used from the 2D one, so only the view is valid - VkImage DummyImages[3][5] = {}; - VkImageView DummyImageViews[3][5] = {}; + VkImage DummyImages[4][5] = {}; + VkImageView DummyImageViews[4][5] = {}; VkWriteDescriptorSet DummyWrites[14] = {}; VkDescriptorImageInfo DummyInfos[14] = {}; VkSampler DummySampler = VK_NULL_HANDLE; VkBuffer DummyBuffer = VK_NULL_HANDLE; - VkBufferView DummyBufferView[3] = {}; + VkBufferView DummyBufferView[4] = {}; std::map TextureViews; diff --git a/renderdoc/driver/vulkan/vk_shaderdebug.cpp b/renderdoc/driver/vulkan/vk_shaderdebug.cpp index 99c0e9392..980c34e92 100644 --- a/renderdoc/driver/vulkan/vk_shaderdebug.cpp +++ b/renderdoc/driver/vulkan/vk_shaderdebug.cpp @@ -677,6 +677,8 @@ public: const VulkanCreationInfo::ImageView &viewProps = m_Creation.m_ImageView[GetResID(view)]; const VulkanCreationInfo::Image &imageProps = m_Creation.m_Image[viewProps.image]; + const bool depthTex = IsDepthOrStencilFormat(viewProps.format); + VkDevice dev = m_pDriver->GetDev(); // how many co-ordinates should there be @@ -1224,7 +1226,7 @@ public: uniformParams.offset.x, uniformParams.offset.y, uniformParams.offset.z)); } - VkPipeline pipe = MakePipe(constParams, 32, uintTex, sintTex); + VkPipeline pipe = MakePipe(constParams, 32, depthTex, uintTex, sintTex); if(pipe == VK_NULL_HANDLE) { @@ -1266,13 +1268,36 @@ public: } // reset descriptor sets to dummy state - uint32_t resetIndex = 0; - if(uintTex) - resetIndex = 1; - else if(sintTex) - resetIndex = 2; - ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), ARRAY_COUNT(m_DebugData.DummyWrites[resetIndex]), - m_DebugData.DummyWrites[resetIndex], 0, NULL); + if(depthTex) + { + // for depth not all descriptors are valid, in particular we skip 3D and cube + uint32_t resetIndex = 3; + + rdcarray writes; + + for(size_t i = 0; i < ARRAY_COUNT(m_DebugData.DummyWrites[resetIndex]); i++) + { + if(m_DebugData.DummyWrites[resetIndex][i].dstBinding != (uint32_t)ShaderDebugBind::Tex3D && + m_DebugData.DummyWrites[resetIndex][i].dstBinding != (uint32_t)ShaderDebugBind::TexCube && + m_DebugData.DummyWrites[resetIndex][i].dstBinding != (uint32_t)ShaderDebugBind::Buffer) + writes.push_back(m_DebugData.DummyWrites[resetIndex][i]); + } + + ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), (uint32_t)writes.count(), writes.data(), 0, + NULL); + } + else + { + uint32_t resetIndex = 0; + if(uintTex) + resetIndex = 1; + else if(sintTex) + resetIndex = 2; + + ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), + ARRAY_COUNT(m_DebugData.DummyWrites[resetIndex]), + m_DebugData.DummyWrites[resetIndex], 0, NULL); + } // overwrite with our data ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), sampler != VK_NULL_HANDLE ? 3 : 2, writeSets, 0, @@ -1386,7 +1411,7 @@ public: ShaderConstParameters pipeParams = {}; pipeParams.operation = (uint32_t)rdcspv::Op::ExtInst; m_DebugData.MathPipe[floatSizeIdx] = - MakePipe(pipeParams, VarTypeByteSize(params[0].type) * 8, false, false); + MakePipe(pipeParams, VarTypeByteSize(params[0].type) * 8, false, false, false); if(m_DebugData.MathPipe[floatSizeIdx] == VK_NULL_HANDLE) { @@ -1725,8 +1750,8 @@ private: return data; } - VkPipeline MakePipe(const ShaderConstParameters ¶ms, uint32_t floatBitSize, bool uintTex, - bool sintTex) + VkPipeline MakePipe(const ShaderConstParameters ¶ms, uint32_t floatBitSize, bool depthTex, + bool uintTex, bool sintTex) { VkSpecializationMapEntry specMaps[sizeof(params) / sizeof(uint32_t)]; for(size_t i = 0; i < ARRAY_COUNT(specMaps); i++) @@ -1743,18 +1768,20 @@ private: specInfo.pMapEntries = specMaps; uint32_t shaderIndex = 0; - if(uintTex) + if(depthTex) shaderIndex = 1; - else if(sintTex) + if(uintTex) shaderIndex = 2; + else if(sintTex) + shaderIndex = 3; if(params.operation == (uint32_t)rdcspv::Op::ExtInst) { - shaderIndex = 3; + shaderIndex = 4; if(floatBitSize == 16) - shaderIndex = 4; - else if(floatBitSize == 64) shaderIndex = 5; + else if(floatBitSize == 64) + shaderIndex = 6; } if(m_DebugData.Module[shaderIndex] == VK_NULL_HANDLE) @@ -1769,7 +1796,7 @@ private: { RDCASSERTMSG("Assume sampling happens with 32-bit float inputs", floatBitSize == 32, floatBitSize); - GenerateSamplingShaderModule(spirv, uintTex, sintTex); + GenerateSamplingShaderModule(spirv, depthTex, uintTex, sintTex); } VkShaderModuleCreateInfo moduleCreateInfo = {VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO}; @@ -1781,8 +1808,9 @@ private: m_pDriver->CheckVkResult(vkr); const char *filename[] = { - "/debug_psgather_float.spv", "/debug_psgather_uint.spv", "/debug_psgather_sint.spv", - "/debug_psmath32.spv", "/debug_psmath16.spv", "/debug_psmath64.spv", + "/debug_psgather_float.spv", "/debug_psgather_depth.spv", "/debug_psgather_uint.spv", + "/debug_psgather_sint.spv", "/debug_psmath32.spv", "/debug_psmath16.spv", + "/debug_psmath64.spv", }; if(!Vulkan_Debug_PSDebugDumpDirPath().empty()) @@ -2173,7 +2201,8 @@ private: editor.AddFunction(func); } - void GenerateSamplingShaderModule(rdcarray &spirv, bool uintTex, bool sintTex) + void GenerateSamplingShaderModule(rdcarray &spirv, bool depthTex, bool uintTex, + bool sintTex) { // this could be done as a glsl shader, but glslang has some bugs compiling the specialisation // constants, so we generate it by hand - which isn't too hard @@ -2359,6 +2388,9 @@ private: { rdcspv::StorageClass storageClass = rdcspv::StorageClass::UniformConstant; + if(depthTex && (i == (size_t)ShaderDebugBind::Tex3D || i == (size_t)ShaderDebugBind::TexCube)) + continue; + if(i == (size_t)ShaderDebugBind::Constants) storageClass = rdcspv::StorageClass::Uniform; @@ -2374,9 +2406,11 @@ private: editor.SetName(bindVars[(size_t)ShaderDebugBind::Tex1D], "Tex1D"); editor.SetName(bindVars[(size_t)ShaderDebugBind::Tex2D], "Tex2D"); - editor.SetName(bindVars[(size_t)ShaderDebugBind::Tex3D], "Tex3D"); + if(!depthTex) + editor.SetName(bindVars[(size_t)ShaderDebugBind::Tex3D], "Tex3D"); editor.SetName(bindVars[(size_t)ShaderDebugBind::Tex2DMS], "Tex2DMS"); - editor.SetName(bindVars[(size_t)ShaderDebugBind::TexCube], "TexCube"); + if(!depthTex) + editor.SetName(bindVars[(size_t)ShaderDebugBind::TexCube], "TexCube"); editor.SetName(bindVars[(size_t)ShaderDebugBind::Buffer], "Buffer"); editor.SetName(bindVars[(size_t)ShaderDebugBind::Sampler], "Sampler"); editor.SetName(bindVars[(size_t)ShaderDebugBind::Constants], "CBuffer"); @@ -2545,6 +2579,9 @@ private: if(i == sampIdx || i == (uint32_t)ShaderDebugBind::Constants) continue; + if(depthTex && (i == (size_t)ShaderDebugBind::Tex3D || i == (size_t)ShaderDebugBind::TexCube)) + continue; + // can't fetch from cubemaps if(i != (uint32_t)ShaderDebugBind::TexCube) { @@ -2659,14 +2696,22 @@ private: cases.add(rdcspv::OpBranch(breakLabel)); } - bool emitDRef = true; - // on Qualcomm we only emit Dref instructions against 2D textures, otherwise the compiler may // crash. if(m_pDriver->GetDriverInfo().QualcommDrefNon2DCompileCrash()) - emitDRef = (i == (uint32_t)ShaderDebugBind::Tex2D); + depthTex &= (i == (uint32_t)ShaderDebugBind::Tex2D); - if(emitDRef) + // VUID-StandaloneSpirv-OpImage-04777 + // OpImage*Dref must not consume an image whose Dim is 3D + // also skip cube + if(i == (uint32_t)ShaderDebugBind::Tex3D || i == (uint32_t)ShaderDebugBind::TexCube) + depthTex = false; + + // don't emit dref's for uint/sint textures + if(uintTex || sintTex) + depthTex = false; + + if(depthTex) { for(rdcspv::Op op : {rdcspv::Op::ImageSampleDrefExplicitLod, rdcspv::Op::ImageSampleDrefImplicitLod}) @@ -2734,6 +2779,9 @@ private: for(rdcspv::Op op : {rdcspv::Op::ImageGather, rdcspv::Op::ImageDrefGather}) { + if(op == rdcspv::Op::ImageDrefGather && !depthTex) + continue; + rdcspv::Id label = editor.MakeId(); targets.push_back({(uint32_t)op * 10 + i, label});