mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-29 21:30:53 +00:00
Implement OpImageQueryLod by faking derivatives on sample quad
This commit is contained in:
@@ -386,6 +386,7 @@ set(data
|
||||
data/glsl/quadresolve.frag
|
||||
data/glsl/quadwrite.frag
|
||||
data/glsl/pixelhistory_primid.frag
|
||||
data/glsl/shaderdebug_sample.vert
|
||||
data/glsl/texdisplay.frag
|
||||
data/glsl/texremap.frag
|
||||
data/glsl/gl_texsample.h
|
||||
|
||||
@@ -64,6 +64,7 @@ DECLARE_EMBED(glsl_deptharr2ms_frag);
|
||||
DECLARE_EMBED(glsl_depthms2arr_frag);
|
||||
DECLARE_EMBED(glsl_gles_texsample_h);
|
||||
DECLARE_EMBED(glsl_pixelhistory_primid_frag);
|
||||
DECLARE_EMBED(glsl_shaderdebug_sample_vert);
|
||||
DECLARE_EMBED(glsl_texremap_frag);
|
||||
|
||||
#undef DECLARE_EMBED
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
layout(location = 0) out vec3 uvw;
|
||||
|
||||
layout(push_constant) uniform PushData
|
||||
{
|
||||
vec4 uvw;
|
||||
vec4 ddx;
|
||||
vec4 ddy;
|
||||
}
|
||||
push;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
const vec4 verts[3] = vec4[3](vec4(-0.75, -0.75, 0.5, 1.0), vec4(1.25, -0.75, 0.5, 1.0),
|
||||
vec4(-0.75, 1.25, 0.5, 1.0));
|
||||
|
||||
gl_Position = verts[gl_VertexIndex];
|
||||
uvw = push.uvw.xyz;
|
||||
if(gl_VertexIndex == 1)
|
||||
uvw += push.ddx.xyz;
|
||||
else if(gl_VertexIndex == 2)
|
||||
uvw += push.ddy.xyz;
|
||||
}
|
||||
@@ -146,6 +146,7 @@ RESOURCE_glsl_gltext_vert TYPE_EMBED "glsl/gltext.vert"
|
||||
RESOURCE_glsl_gltext_frag TYPE_EMBED "glsl/gltext.frag"
|
||||
RESOURCE_glsl_glsl_globals_h TYPE_EMBED "glsl/glsl_globals.h"
|
||||
RESOURCE_glsl_texremap_frag TYPE_EMBED "glsl/texremap.frag"
|
||||
RESOURCE_glsl_shaderdebug_sample_vert TYPE_EMBED "glsl/shaderdebug_sample.vert"
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#define RESOURCE_glsl_glsl_globals_h 440
|
||||
#define RESOURCE_glsl_texremap_frag 441
|
||||
#define RESOURCE_glsl_pixelhistory_primid_frag 442
|
||||
#define RESOURCE_glsl_shaderdebug_sample_vert 443
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
|
||||
@@ -1986,6 +1986,7 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray<ThreadState>
|
||||
case Op::ImageFetch:
|
||||
case Op::ImageGather:
|
||||
case Op::ImageDrefGather:
|
||||
case Op::ImageQueryLod:
|
||||
case Op::ImageSampleExplicitLod:
|
||||
case Op::ImageSampleImplicitLod:
|
||||
case Op::ImageSampleDrefExplicitLod:
|
||||
@@ -2033,6 +2034,15 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray<ThreadState>
|
||||
gather = GatherChannel::Red;
|
||||
compare = GetSrc(image.dref);
|
||||
}
|
||||
else if(opdata.op == Op::ImageQueryLod)
|
||||
{
|
||||
OpImageQueryLod image(it);
|
||||
|
||||
sampler = img = GetSrc(image.sampledImage);
|
||||
uv = GetSrc(image.coordinate);
|
||||
|
||||
derivId = image.coordinate;
|
||||
}
|
||||
else if(opdata.op == Op::ImageSampleExplicitLod)
|
||||
{
|
||||
OpImageSampleExplicitLod image(it);
|
||||
@@ -2420,18 +2430,6 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray<ThreadState>
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO image lod query (from implicit lod)
|
||||
case Op::ImageQueryLod:
|
||||
{
|
||||
RDCERR("Image lod query not yet implemented.");
|
||||
|
||||
ShaderVariable var("", 0U, 0U, 0U, 0U);
|
||||
var.columns = 1;
|
||||
|
||||
SetDst(opdata.result, var);
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO image load/store
|
||||
case Op::ImageRead:
|
||||
case Op::ImageWrite:
|
||||
|
||||
@@ -93,6 +93,8 @@ static const BuiltinShaderConfig builtinShaders[] = {
|
||||
rdcspv::ShaderStage::Fragment, FeatureCheck::NoCheck, true},
|
||||
{BuiltinShader::PixelHistoryPrimIDFS, EmbeddedResource(glsl_pixelhistory_primid_frag),
|
||||
rdcspv::ShaderStage::Fragment, FeatureCheck::NoCheck, true},
|
||||
{BuiltinShader::ShaderDebugSampleVS, EmbeddedResource(glsl_shaderdebug_sample_vert),
|
||||
rdcspv::ShaderStage::Vertex, FeatureCheck::NoCheck, true},
|
||||
};
|
||||
|
||||
RDCCOMPILE_ASSERT(ARRAY_COUNT(builtinShaders) == arraydim<BuiltinShader>(),
|
||||
|
||||
@@ -55,6 +55,7 @@ enum class BuiltinShader
|
||||
TexRemapUInt,
|
||||
TexRemapSInt,
|
||||
PixelHistoryPrimIDFS,
|
||||
ShaderDebugSampleVS,
|
||||
Count,
|
||||
};
|
||||
|
||||
|
||||
@@ -755,6 +755,7 @@ public:
|
||||
|
||||
break;
|
||||
}
|
||||
case rdcspv::Op::ImageQueryLod:
|
||||
case rdcspv::Op::ImageSampleExplicitLod:
|
||||
case rdcspv::Op::ImageSampleImplicitLod:
|
||||
case rdcspv::Op::ImageSampleProjExplicitLod:
|
||||
@@ -812,7 +813,7 @@ public:
|
||||
}
|
||||
|
||||
if(opcode == rdcspv::Op::ImageSampleImplicitLod ||
|
||||
opcode == rdcspv::Op::ImageSampleProjImplicitLod)
|
||||
opcode == rdcspv::Op::ImageSampleProjImplicitLod || opcode == rdcspv::Op::ImageQueryLod)
|
||||
{
|
||||
// use grad to sub in for the implicit lod
|
||||
constParams.useGradOrGatherOffsets = VK_TRUE;
|
||||
@@ -941,6 +942,14 @@ public:
|
||||
Unwrap(m_DebugData.PipeLayout), 0, 1,
|
||||
UnwrapPtr(m_DebugData.DescSet), 0, NULL);
|
||||
|
||||
// push uvw/ddx/ddy for the vertex shader
|
||||
ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(m_DebugData.PipeLayout), VK_SHADER_STAGE_ALL,
|
||||
sizeof(Vec4f) * 0, sizeof(Vec3f), &uniformParams.uvw);
|
||||
ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(m_DebugData.PipeLayout), VK_SHADER_STAGE_ALL,
|
||||
sizeof(Vec4f) * 1, sizeof(Vec3f), &uniformParams.ddx);
|
||||
ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(m_DebugData.PipeLayout), VK_SHADER_STAGE_ALL,
|
||||
sizeof(Vec4f) * 2, sizeof(Vec3f), &uniformParams.ddy);
|
||||
|
||||
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), 4, 1, 0, 0);
|
||||
|
||||
ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd));
|
||||
@@ -1230,7 +1239,8 @@ private:
|
||||
|
||||
const VkPipelineShaderStageCreateInfo shaderStages[2] = {
|
||||
{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, NULL, 0, VK_SHADER_STAGE_VERTEX_BIT,
|
||||
m_pDriver->GetShaderCache()->GetBuiltinModule(BuiltinShader::BlitVS), "main", NULL},
|
||||
m_pDriver->GetShaderCache()->GetBuiltinModule(BuiltinShader::ShaderDebugSampleVS), "main",
|
||||
NULL},
|
||||
{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, NULL, 0, VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
m_DebugData.Module[shaderIndex], "main", &specInfo},
|
||||
};
|
||||
@@ -1545,6 +1555,7 @@ private:
|
||||
editor.CreateEmpty(1, 0);
|
||||
|
||||
editor.AddCapability(rdcspv::Capability::Shader);
|
||||
editor.AddCapability(rdcspv::Capability::ImageQuery);
|
||||
editor.AddCapability(rdcspv::Capability::Sampled1D);
|
||||
editor.AddCapability(rdcspv::Capability::SampledBuffer);
|
||||
|
||||
@@ -1567,6 +1578,7 @@ private:
|
||||
rdcspv::Id v3i32 = editor.DeclareType(rdcspv::Vector(rdcspv::scalar<int32_t>(), 3));
|
||||
rdcspv::Id v2f32 = editor.DeclareType(rdcspv::Vector(rdcspv::scalar<float>(), 2));
|
||||
rdcspv::Id v3f32 = editor.DeclareType(rdcspv::Vector(rdcspv::scalar<float>(), 3));
|
||||
rdcspv::Id v4f32 = editor.DeclareType(rdcspv::Vector(rdcspv::scalar<float>(), 4));
|
||||
|
||||
// int2[4]
|
||||
rdcspv::Id a4v2i32 = editor.AddType(
|
||||
@@ -1734,10 +1746,18 @@ private:
|
||||
editor.SetName(bindVars[(size_t)ShaderDebugBind::Sampler], "Sampler");
|
||||
editor.SetName(bindVars[(size_t)ShaderDebugBind::Constants], "CBuffer");
|
||||
|
||||
rdcspv::Id uvw_ptr = editor.DeclareType(rdcspv::Pointer(v3f32, rdcspv::StorageClass::Input));
|
||||
rdcspv::Id input_uvw_var =
|
||||
editor.AddVariable(rdcspv::OpVariable(uvw_ptr, editor.MakeId(), rdcspv::StorageClass::Input));
|
||||
editor.AddDecoration(rdcspv::OpDecorate(
|
||||
input_uvw_var, rdcspv::DecorationParam<rdcspv::Decoration::Location>(0)));
|
||||
|
||||
editor.SetName(input_uvw_var, "uvw");
|
||||
|
||||
// register the entry point
|
||||
editor.AddOperation(
|
||||
editor.Begin(rdcspv::Section::EntryPoints),
|
||||
rdcspv::OpEntryPoint(rdcspv::ExecutionModel::Fragment, entryId, "main", {outVar}));
|
||||
editor.AddOperation(editor.Begin(rdcspv::Section::EntryPoints),
|
||||
rdcspv::OpEntryPoint(rdcspv::ExecutionModel::Fragment, entryId, "main",
|
||||
{input_uvw_var, outVar}));
|
||||
editor.AddOperation(editor.Begin(rdcspv::Section::ExecutionMode),
|
||||
rdcspv::OpExecutionMode(entryId, rdcspv::ExecutionMode::OriginUpperLeft));
|
||||
|
||||
@@ -1794,6 +1814,10 @@ private:
|
||||
editor.SetName(offset_xy, "offset_xy");
|
||||
editor.SetName(offset_xyz, "offset_xyz");
|
||||
|
||||
rdcspv::Id input_uvw = func.add(rdcspv::OpLoad(v3f32, editor.MakeId(), input_uvw_var));
|
||||
rdcspv::Id input_uv =
|
||||
func.add(rdcspv::OpVectorShuffle(v2f32, editor.MakeId(), input_uvw, input_uvw, {0, 1}));
|
||||
|
||||
// first store NULL data in, so the output is always initialised
|
||||
|
||||
rdcspv::Id breakLabel = editor.MakeId();
|
||||
@@ -1820,6 +1844,16 @@ private:
|
||||
texel_u, // Buffer - u
|
||||
};
|
||||
|
||||
// only used for QueryLod, so we can ignore MSAA/Buffer
|
||||
rdcspv::Id input_coord[(uint32_t)ShaderDebugBind::Count] = {
|
||||
rdcspv::Id(),
|
||||
input_uv, // 1D - u and array
|
||||
input_uvw, // 2D - u,v and array
|
||||
input_uvw, // 3D - u,v,w
|
||||
rdcspv::Id(), // 2DMS
|
||||
rdcspv::Id(), // Buffer
|
||||
};
|
||||
|
||||
rdcspv::Id coord[(uint32_t)ShaderDebugBind::Count] = {
|
||||
rdcspv::Id(),
|
||||
uv, // 1D - u and array
|
||||
@@ -1892,6 +1926,35 @@ private:
|
||||
if(i == (uint32_t)ShaderDebugBind::Buffer || i == (uint32_t)ShaderDebugBind::Tex2DMS)
|
||||
continue;
|
||||
|
||||
{
|
||||
rdcspv::Op op = rdcspv::Op::ImageQueryLod;
|
||||
|
||||
rdcspv::Id label = editor.MakeId();
|
||||
targets.push_back({(uint32_t)op * 10 + i, label});
|
||||
|
||||
cases.add(rdcspv::OpLabel(label));
|
||||
rdcspv::Id loadedImage =
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), bindVars[i]));
|
||||
rdcspv::Id loadedSampler =
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[sampIdx], editor.MakeId(), bindVars[sampIdx]));
|
||||
|
||||
rdcspv::Id combined = cases.add(rdcspv::OpSampledImage(
|
||||
texSampCombinedTypes[i], editor.MakeId(), loadedImage, loadedSampler));
|
||||
|
||||
rdcspv::Id sampleResult =
|
||||
cases.add(rdcspv::OpImageQueryLod(v2f32, editor.MakeId(), combined, input_coord[i]));
|
||||
sampleResult = cases.add(rdcspv::OpVectorShuffle(v4f32, editor.MakeId(), sampleResult,
|
||||
sampleResult, {0, 1, 0, 1}));
|
||||
|
||||
// if we're sampling from an integer texture the output variable will be the same type.
|
||||
// Just bitcast the float bits into it, which will come out the other side the right type.
|
||||
if(uintTex || sintTex)
|
||||
sampleResult = cases.add(rdcspv::OpBitcast(resultType, editor.MakeId(), sampleResult));
|
||||
|
||||
cases.add(rdcspv::OpStore(outVar, sampleResult));
|
||||
cases.add(rdcspv::OpBranch(breakLabel));
|
||||
}
|
||||
|
||||
for(rdcspv::Op op : {rdcspv::Op::ImageSampleExplicitLod, rdcspv::Op::ImageSampleImplicitLod})
|
||||
{
|
||||
rdcspv::Id label = editor.MakeId();
|
||||
|
||||
@@ -602,6 +602,7 @@
|
||||
<None Include="data\glsl\pixelhistory_primid.frag" />
|
||||
<None Include="data\glsl\quadresolve.frag" />
|
||||
<None Include="data\glsl\quadwrite.frag" />
|
||||
<None Include="data\glsl\shaderdebug_sample.vert" />
|
||||
<None Include="data\glsl\texdisplay.frag" />
|
||||
<None Include="data\glsl\texremap.frag" />
|
||||
<None Include="data\glsl\vktext.frag" />
|
||||
|
||||
@@ -1069,6 +1069,9 @@
|
||||
<None Include="data\hlsl\texremap.hlsl">
|
||||
<Filter>Resources\hlsl</Filter>
|
||||
</None>
|
||||
<None Include="data\glsl\shaderdebug_sample.vert">
|
||||
<Filter>Resources\glsl</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="data\renderdoc.rc">
|
||||
|
||||
@@ -1074,6 +1074,12 @@ void main()
|
||||
Color = textureProj(linearSampledImage, vec3(inpos, 0.5f));
|
||||
break;
|
||||
}
|
||||
case 130:
|
||||
{
|
||||
Color.xy = textureQueryLod(linearSampledImage, inpos);
|
||||
Color.zw = textureQueryLod(linearSampledImage, vec2(1.0f, 1.0f)/inpos);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user