From 7082f4eb4477162cd06e6872a5757e123a7c462d Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 16 Apr 2020 16:16:28 +0100 Subject: [PATCH] Implement image dimension query opcodes --- .../driver/shaders/spirv/spirv_debug.cpp | 19 +++++ .../shaders/spirv/spirv_debug_setup.cpp | 12 +-- renderdoc/driver/vulkan/vk_shaderdebug.cpp | 82 ++++++++++++++----- util/test/demos/vk/vk_shader_debug_zoo.cpp | 74 ++++++++++++++++- 4 files changed, 155 insertions(+), 32 deletions(-) diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.cpp b/renderdoc/driver/shaders/spirv/spirv_debug.cpp index 809033005..ef6a6929a 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug.cpp @@ -1824,6 +1824,10 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray SetDst(image.result, var); break; } + case Op::ImageQueryLevels: + case Op::ImageQuerySamples: + case Op::ImageQuerySize: + case Op::ImageQuerySizeLod: case Op::ImageFetch: case Op::ImageSampleExplicitLod: case Op::ImageSampleImplicitLod: @@ -1865,6 +1869,21 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray derivId = image.coordinate; } + else if(opdata.op == Op::ImageQueryLevels || opdata.op == Op::ImageQuerySamples || + opdata.op == Op::ImageQuerySize) + { + // these opcodes are all identical, they just query a property of the image + OpImageQueryLevels query(it); + + img = GetSrc(query.image); + } + else if(opdata.op == Op::ImageQuerySizeLod) + { + OpImageQuerySizeLod query(it); + + img = GetSrc(query.image); + operands.setLod(query.levelofDetail); + } if(derivId != Id()) { diff --git a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp index a8db6a88e..39338900a 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp @@ -166,6 +166,7 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader case Capability::ImageBuffer: case Capability::ImageMSArray: case Capability::StorageImageExtendedFormats: + case Capability::ImageQuery: case Capability::DerivativeControl: case Capability::TransformFeedback: case Capability::GeometryStreams: @@ -179,6 +180,7 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader case Capability::MultiView: case Capability::SampleMaskPostDepthCoverage: case Capability::StencilExportEXT: + case Capability::ShaderClockKHR: case Capability::ShaderViewportIndexLayerEXT: case Capability::FragmentFullyCoveredEXT: case Capability::FragmentDensityEXT: @@ -196,6 +198,7 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader case Capability::StorageTexelBufferArrayNonUniformIndexing: case Capability::VulkanMemoryModel: case Capability::VulkanMemoryModelDeviceScope: + case Capability::DemoteToHelperInvocationEXT: { supported = true; break; @@ -203,18 +206,12 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader // we plan to support these but needs additional testing/proving - // image queries - case Capability::ImageQuery: - // image gather operations case Capability::ImageGatherExtended: // image storage case Capability::StorageImageMultisample: - // demote to helper - case Capability::DemoteToHelperInvocationEXT: - // all these are related to non-32-bit types case Capability::Float16Buffer: case Capability::Float16: @@ -252,9 +249,6 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader case Capability::RoundingModeRTE: case Capability::RoundingModeRTZ: - // shader clock - case Capability::ShaderClockKHR: - // group instructions case Capability::Groups: case Capability::GroupNonUniform: diff --git a/renderdoc/driver/vulkan/vk_shaderdebug.cpp b/renderdoc/driver/vulkan/vk_shaderdebug.cpp index f98350852..7acffd5ab 100644 --- a/renderdoc/driver/vulkan/vk_shaderdebug.cpp +++ b/renderdoc/driver/vulkan/vk_shaderdebug.cpp @@ -420,6 +420,69 @@ public: return false; } + switch(imageType) + { + case VK_IMAGE_TYPE_1D: params.dim = ShaderDebugBind::Tex1D; break; + case VK_IMAGE_TYPE_2D: + params.dim = ShaderDebugBind::Tex2D; + if(samples > 1) + params.dim = ShaderDebugBind::Tex2DMS; + break; + case VK_IMAGE_TYPE_3D: params.dim = ShaderDebugBind::Tex3D; break; + default: + { + RDCERR("Unsupported image type %s", ToStr(imageType).c_str()); + return false; + } + } + + if(buffer) + { + params.dim = ShaderDebugBind::Buffer; + coords = gradCoords = 1; + } + + // handle query opcodes now + switch(opcode) + { + case rdcspv::Op::ImageQueryLevels: + { + output.value.u.x = viewProps.range.levelCount; + if(viewProps.range.levelCount == VK_REMAINING_MIP_LEVELS) + output.value.u.x = imageProps.mipLevels - viewProps.range.baseMipLevel; + return true; + } + case rdcspv::Op::ImageQuerySamples: + { + output.value.u.x = (uint32_t)imageProps.samples; + return true; + } + case rdcspv::Op::ImageQuerySize: + case rdcspv::Op::ImageQuerySizeLod: + { + uint32_t mip = viewProps.range.baseMipLevel; + + if(opcode == rdcspv::Op::ImageQuerySizeLod) + mip += lane.GetSrc(operands.lod).value.u.x; + + int i = 0; + output.value.uv[i++] = RDCMAX(1U, imageProps.extent.width >> mip); + if(coords >= 2) + output.value.uv[i++] = RDCMAX(1U, imageProps.extent.height >> mip); + if(viewProps.viewType == VK_IMAGE_VIEW_TYPE_3D) + output.value.uv[i++] = RDCMAX(1U, imageProps.extent.depth >> mip); + + if(viewProps.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY || + viewProps.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) + output.value.uv[i++] = imageProps.arrayLayers; + else if(viewProps.viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) + output.value.uv[i++] = imageProps.arrayLayers / 6; + + return true; + } + default: break; + } + // create our own view (if we haven't already for this view) so we can promote to array VkImageView sampleView = m_SampleViews[GetResID(view)]; if(sampleView == VK_NULL_HANDLE) @@ -520,25 +583,6 @@ public: params.operation = (uint32_t)opcode; - switch(imageType) - { - case VK_IMAGE_TYPE_1D: params.dim = ShaderDebugBind::Tex1D; break; - case VK_IMAGE_TYPE_2D: - params.dim = ShaderDebugBind::Tex2D; - if(samples > 1) - params.dim = ShaderDebugBind::Tex2DMS; - break; - case VK_IMAGE_TYPE_3D: params.dim = ShaderDebugBind::Tex3D; break; - default: - { - RDCERR("Unsupported image type %s", ToStr(imageType).c_str()); - return false; - } - } - - if(buffer) - params.dim = ShaderDebugBind::Buffer; - switch(opcode) { case rdcspv::Op::ImageFetch: diff --git a/util/test/demos/vk/vk_shader_debug_zoo.cpp b/util/test/demos/vk/vk_shader_debug_zoo.cpp index d3250bc78..2f8725019 100644 --- a/util/test/demos/vk/vk_shader_debug_zoo.cpp +++ b/util/test/demos/vk/vk_shader_debug_zoo.cpp @@ -134,6 +134,9 @@ layout(set = 0, binding = 5, std430) buffer storebuftype //layout(set = 0, binding = 7, rgba32f) uniform coherent samplerBuffer texBuffer; //layout(set = 0, binding = 8, rgba32f) uniform coherent imageBuffer storeTexBuffer; +layout(set = 0, binding = 20) uniform sampler2DArray queryTest; +layout(set = 0, binding = 21) uniform sampler2DMSArray queryTestMS; + layout(push_constant) uniform PushData { layout(offset = 16) ivec4 data; } push; @@ -881,6 +884,31 @@ void main() uintBitsToFloat(bitfieldInsert(a, af, 4, 5)), intBitsToFloat(bitfieldInsert(b, bf, 4, 5))); break; } + case 106: + { + Color = vec4(float(textureQueryLevels(queryTest)), float(textureSamples(queryTestMS)), 0.0f, 1.0f); + break; + } + case 107: + { + Color = vec4(vec3(textureSize(queryTest, 0)), 1.0f); + break; + } + case 108: + { + Color = vec4(vec3(textureSize(queryTest, 1)), 1.0f); + break; + } + case 109: + { + Color = vec4(vec3(textureSize(queryTestMS)), 1.0f); + break; + } + case 110: + { + Color = vec4(vec3(textureSize(queryTestMS)), 1.0f); + break; + } default: break; } } @@ -2033,6 +2061,8 @@ void main() {6, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, {7, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, {8, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, + {20, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, + {21, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT}, })); VkPipelineLayout layout = createPipelineLayout(vkh::PipelineLayoutCreateInfo( @@ -2118,6 +2148,21 @@ void main() Texture rgba8; LoadXPM(SmileyTexture, rgba8); + AllocatedImage queryTest(this, vkh::ImageCreateInfo(183, 347, 0, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_SAMPLED_BIT, 4, 3), + VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY})); + + VkImageView queryTestView = createImageView(vkh::ImageViewCreateInfo( + queryTest.image, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_R8G8B8A8_UNORM)); + + AllocatedImage queryTestMS( + this, vkh::ImageCreateInfo(183, 347, 0, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_SAMPLED_BIT, 1, 5, VK_SAMPLE_COUNT_4_BIT), + VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY})); + + VkImageView queryTestMSView = createImageView(vkh::ImageViewCreateInfo( + queryTestMS.image, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_R8G8B8A8_UNORM)); + AllocatedImage smiley( this, vkh::ImageCreateInfo(rgba8.width, rgba8.height, 0, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT), @@ -2137,10 +2182,15 @@ void main() vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo()); vkh::cmdPipelineBarrier( - cmd, { - vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, smiley.image), - }); + cmd, + { + vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, smiley.image), + vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_GENERAL, queryTest.image), + vkh::ImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_GENERAL, queryTestMS.image), + }); VkBufferImageCopy copy = {}; copy.imageExtent = {rgba8.width, rgba8.height, 1}; @@ -2166,6 +2216,7 @@ void main() VkSampler pointsampler = VK_NULL_HANDLE; VkSampler linearsampler = VK_NULL_HANDLE; + VkSampler mipsampler = VK_NULL_HANDLE; VkSamplerCreateInfo sampInfo = {VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}; sampInfo.magFilter = VK_FILTER_NEAREST; @@ -2178,6 +2229,10 @@ void main() vkCreateSampler(device, &sampInfo, NULL, &linearsampler); + sampInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + + vkCreateSampler(device, &sampInfo, NULL, &mipsampler); + VkDescriptorSet descset = allocateDescriptorSet(setlayout); Vec4f cbufferdata[16] = {}; @@ -2225,6 +2280,9 @@ void main() setName(pointsampler, "pointsampler"); setName(linearsampler, "linearsampler"); + setName(mipsampler, "mipsampler"); + setName(queryTest.image, "queryTest"); + setName(queryTestMS.image, "queryTestMS"); setName(smiley.image, "smiley"); setName(texbuffer.buffer, "texbuffer"); setName(store_buffer.buffer, "store_buffer"); @@ -2258,6 +2316,13 @@ void main() vkh::WriteDescriptorSet(descset, 7, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, {bufview}), vkh::WriteDescriptorSet(descset, 8, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, {store_bufview}), + + vkh::WriteDescriptorSet( + descset, 20, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + {vkh::DescriptorImageInfo(queryTestView, VK_IMAGE_LAYOUT_GENERAL, mipsampler)}), + vkh::WriteDescriptorSet( + descset, 21, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + {vkh::DescriptorImageInfo(queryTestMSView, VK_IMAGE_LAYOUT_GENERAL, mipsampler)}), }); while(Running()) @@ -2382,6 +2447,7 @@ void main() vkDestroySampler(device, pointsampler, NULL); vkDestroySampler(device, linearsampler, NULL); + vkDestroySampler(device, mipsampler, NULL); return 0; }