Generate SPIR-V shader to implement some image samples on 2D image

This commit is contained in:
baldurk
2020-04-10 20:52:09 +01:00
parent 5af5f847a0
commit a61822cfe1
3 changed files with 266 additions and 27 deletions
@@ -1575,7 +1575,7 @@ void ThreadState::StepNext(ShaderDebugState *state,
result.type = resultType.scalar().Type();
BindpointIndex samplerIndex = BindpointIndex(~0U, ~0U, ~0U);
if(sampler.type == VarType::Sampler)
if(sampler.type == VarType::Sampler || sampler.type == VarType::ReadOnlyResource)
samplerIndex = sampler.GetBinding();
if(!debugger.GetAPIWrapper()->CalculateSampleGather(
+240 -22
View File
@@ -71,26 +71,33 @@ struct DescSetSnapshot
};
// should match the descriptor set layout created in ShaderDebugData::Init()
enum ShaderDebugBind
enum class ShaderDebugBind
{
Tex1D = 1,
First = Tex1D,
Tex2D,
Tex3D,
Tex2DMS,
Buffer,
Sampler,
Count,
};
struct Vec3i
{
int32_t x, y, z;
};
struct ShaderDebugParameters
{
uint32_t operation;
ShaderDebugBind dim;
int texel_uvw[3];
Vec3i texel_uvw;
int texel_lod;
Vec3f uvw;
Vec3f ddx;
Vec3f ddy;
int offset[3];
Vec3i offset;
int sampleIdx;
float compare;
float bias;
@@ -335,6 +342,8 @@ public:
VkImageView view = imageInfo.imageView;
VkImageLayout layout = imageInfo.imageLayout;
// promote view to Array view
const VulkanCreationInfo::Image &imageProps =
m_Creation.m_Image[m_Creation.m_ImageView[GetResID(view)].image];
VkImageType imageType = imageProps.type;
@@ -365,14 +374,32 @@ public:
{
case rdcspv::Op::ImageFetch:
{
params.texel_uvw[0] = uv.value.u.x;
params.texel_uvw[1] = uv.value.u.y;
params.texel_uvw[2] = uv.value.u.z;
// TODO only upload relevant coords
params.texel_uvw.x = uv.value.u.x;
params.texel_uvw.y = uv.value.u.y;
params.texel_uvw.z = uv.value.u.z;
if(!buffer)
params.texel_lod = lane.GetSrc(operands.lod).value.i.x;
break;
}
case rdcspv::Op::ImageSampleExplicitLod: { break;
case rdcspv::Op::ImageSampleExplicitLod:
{
// TODO only upload relevant coords
params.uvw.x = uv.value.f.x;
params.uvw.y = uv.value.f.y;
params.uvw.z = uv.value.f.z;
if(operands.flags & rdcspv::ImageOperands::Lod)
params.lod = lane.GetSrc(operands.lod).value.f.x;
else
RDCERR("Grad variant not supported");
if(operands.flags & rdcspv::ImageOperands::ConstOffset)
{
ShaderVariable constOffset = lane.GetSrc(operands.constOffset);
params.offset.x = constOffset.value.i.x;
params.offset.y = constOffset.value.i.y;
params.offset.z = constOffset.value.i.z;
}
break;
}
case rdcspv::Op::ImageSampleImplicitLod: { break;
}
@@ -549,7 +576,7 @@ private:
VkSpecializationMapEntry specMaps[sizeof(params) / sizeof(uint32_t)];
for(size_t i = 0; i < ARRAY_COUNT(specMaps); i++)
{
specMaps[i].constantID = uint32_t(i + i);
specMaps[i].constantID = uint32_t(i);
specMaps[i].offset = uint32_t(sizeof(uint32_t) * i);
specMaps[i].size = sizeof(uint32_t);
}
@@ -693,9 +720,10 @@ private:
editor.CreateEmpty(1, 0);
editor.AddCapability(rdcspv::Capability::Shader);
editor.AddCapability(rdcspv::Capability::Sampled1D);
editor.AddCapability(rdcspv::Capability::SampledBuffer);
rdcspv::Id entryId = editor.MakeId();
rdcarray<rdcspv::Id> globals;
editor.AddOperation(
editor.Begin(rdcspv::Section::MemoryModel),
@@ -705,28 +733,122 @@ private:
rdcspv::Id i32 = editor.DeclareType(rdcspv::scalar<int32_t>());
rdcspv::Id f32 = editor.DeclareType(rdcspv::scalar<float>());
rdcspv::Id v2i32 = editor.DeclareType(rdcspv::Vector(rdcspv::scalar<int32_t>(), 2));
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::Scalar base = rdcspv::scalar<float>();
if(uintTex)
base = rdcspv::scalar<uint32_t>();
else if(sintTex)
base = rdcspv::scalar<int32_t>();
rdcspv::Id resultType = editor.DeclareType(rdcspv::Vector(base, 4));
// add specialisation constants for all the parameters
#define SPEC_ID(name) uint32_t(offsetof(ShaderDebugParameters, name) / sizeof(uint32_t))
rdcspv::Id operation = editor.AddSpecConstantImmediate<uint32_t>(0U, SPEC_ID(operation));
rdcspv::Id dim = editor.AddSpecConstantImmediate<uint32_t>(0U, SPEC_ID(dim));
rdcspv::Id texel_u = editor.AddSpecConstantImmediate<int32_t>(0U, SPEC_ID(texel_uvw.x));
rdcspv::Id texel_v = editor.AddSpecConstantImmediate<int32_t>(0U, SPEC_ID(texel_uvw.y));
rdcspv::Id texel_w = editor.AddSpecConstantImmediate<int32_t>(0U, SPEC_ID(texel_uvw.z));
rdcspv::Id texel_lod = editor.AddSpecConstantImmediate<int32_t>(0U, SPEC_ID(texel_lod));
rdcspv::Id u = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(uvw.x));
rdcspv::Id v = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(uvw.y));
rdcspv::Id w = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(uvw.z));
rdcspv::Id dudx = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(ddx.x));
rdcspv::Id dvdx = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(ddx.y));
rdcspv::Id dwdx = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(ddx.z));
rdcspv::Id dudy = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(ddy.x));
rdcspv::Id dvdy = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(ddy.y));
rdcspv::Id dwdy = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(ddy.z));
rdcspv::Id offset_x = editor.AddSpecConstantImmediate<int32_t>(0U, SPEC_ID(offset.x));
rdcspv::Id offset_y = editor.AddSpecConstantImmediate<int32_t>(0U, SPEC_ID(offset.y));
rdcspv::Id offset_z = editor.AddSpecConstantImmediate<int32_t>(0U, SPEC_ID(offset.z));
rdcspv::Id sampleIdx = editor.AddSpecConstantImmediate<int32_t>(0U, SPEC_ID(sampleIdx));
rdcspv::Id compare = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(compare));
rdcspv::Id bias = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(bias));
rdcspv::Id lod = editor.AddSpecConstantImmediate<float>(0U, SPEC_ID(lod));
rdcspv::Id gatherChannel = editor.AddSpecConstantImmediate<int32_t>(0U, SPEC_ID(gatherChannel));
rdcspv::Id texel_uv = editor.AddConstant(
rdcspv::OpSpecConstantComposite(v2i32, editor.MakeId(), {texel_u, texel_v}));
rdcspv::Id texel_uvw = editor.AddConstant(
rdcspv::OpSpecConstantComposite(v3i32, editor.MakeId(), {texel_u, texel_v, texel_w}));
rdcspv::Id uv =
editor.AddConstant(rdcspv::OpSpecConstantComposite(v2f32, editor.MakeId(), {u, v}));
rdcspv::Id uvw =
editor.AddConstant(rdcspv::OpSpecConstantComposite(v3f32, editor.MakeId(), {u, v, w}));
rdcspv::Id ddx_uv =
editor.AddConstant(rdcspv::OpSpecConstantComposite(v2f32, editor.MakeId(), {dudx, dvdx}));
rdcspv::Id ddx_uvw = editor.AddConstant(
rdcspv::OpSpecConstantComposite(v3f32, editor.MakeId(), {dudx, dvdx, dwdx}));
rdcspv::Id ddy_uv =
editor.AddConstant(rdcspv::OpSpecConstantComposite(v2f32, editor.MakeId(), {dudy, dvdy}));
rdcspv::Id ddy_uvw = editor.AddConstant(
rdcspv::OpSpecConstantComposite(v3f32, editor.MakeId(), {dudy, dvdy, dwdy}));
rdcspv::Id offset_xy = editor.AddConstant(
rdcspv::OpSpecConstantComposite(v2i32, editor.MakeId(), {offset_x, offset_y}));
rdcspv::Id offset_xyz = editor.AddConstant(
rdcspv::OpSpecConstantComposite(v3i32, editor.MakeId(), {offset_x, offset_y, offset_z}));
// create the output. It's always a 4-wide vector
rdcspv::Id outType = editor.DeclareType(rdcspv::Vector(base, 4));
rdcspv::Id outPtrType =
editor.DeclareType(rdcspv::Pointer(outType, rdcspv::StorageClass::Output));
editor.DeclareType(rdcspv::Pointer(resultType, rdcspv::StorageClass::Output));
rdcspv::Id outVar = editor.AddVariable(
rdcspv::OpVariable(outPtrType, editor.MakeId(), rdcspv::StorageClass::Output));
editor.AddDecoration(
rdcspv::OpDecorate(outVar, rdcspv::DecorationParam<rdcspv::Decoration::Location>(0)));
globals.push_back(outVar);
rdcspv::ImageFormat unk = rdcspv::ImageFormat::Unknown;
// create the five textures and sampler
rdcspv::Id texSampTypes[ShaderDebugBind::Count] = {
rdcspv::Id(),
editor.DeclareType(rdcspv::Image(base, rdcspv::Dim::_1D, 0, 1, 0, 1, unk)),
editor.DeclareType(rdcspv::Image(base, rdcspv::Dim::_2D, 0, 1, 0, 1, unk)),
editor.DeclareType(rdcspv::Image(base, rdcspv::Dim::_3D, 0, 1, 0, 1, unk)),
editor.DeclareType(rdcspv::Image(base, rdcspv::Dim::_2D, 0, 1, 1, 1, unk)),
editor.DeclareType(rdcspv::Image(base, rdcspv::Dim::Buffer, 0, 1, 0, 1, unk)),
editor.DeclareType(rdcspv::Sampler()),
};
rdcspv::Id texSampVars[ShaderDebugBind::Count];
rdcspv::Id texSampCombinedTypes[ShaderDebugBind::Count] = {
rdcspv::Id(),
editor.DeclareType(rdcspv::SampledImage(texSampTypes[1])),
editor.DeclareType(rdcspv::SampledImage(texSampTypes[2])),
editor.DeclareType(rdcspv::SampledImage(texSampTypes[3])),
editor.DeclareType(rdcspv::SampledImage(texSampTypes[4])),
editor.DeclareType(rdcspv::SampledImage(texSampTypes[5])),
rdcspv::Id(),
};
for(size_t i = (size_t)ShaderDebugBind::First; i < (size_t)ShaderDebugBind::Count; i++)
{
rdcspv::Id ptrType =
editor.DeclareType(rdcspv::Pointer(texSampTypes[i], rdcspv::StorageClass::UniformConstant));
texSampVars[i] = editor.AddVariable(
rdcspv::OpVariable(ptrType, editor.MakeId(), rdcspv::StorageClass::UniformConstant));
editor.AddDecoration(rdcspv::OpDecorate(
texSampVars[i], rdcspv::DecorationParam<rdcspv::Decoration::DescriptorSet>(0U)));
editor.AddDecoration(rdcspv::OpDecorate(
texSampVars[i], rdcspv::DecorationParam<rdcspv::Decoration::Binding>((uint32_t)i)));
}
rdcspv::Id sampVar = texSampVars[(size_t)ShaderDebugBind::Sampler];
// register the entry point
editor.AddOperation(
editor.Begin(rdcspv::Section::EntryPoints),
rdcspv::OpEntryPoint(rdcspv::ExecutionModel::Fragment, entryId, "main", globals));
rdcspv::OpEntryPoint(rdcspv::ExecutionModel::Fragment, entryId, "main", {outVar}));
editor.AddOperation(editor.Begin(rdcspv::Section::ExecutionMode),
rdcspv::OpExecutionMode(entryId, rdcspv::ExecutionMode::OriginUpperLeft));
@@ -738,18 +860,114 @@ private:
func.add(rdcspv::OpLabel(editor.MakeId()));
// first store NULL data in, so the output is always initialised
func.add(rdcspv::OpStore(outVar,
editor.AddConstant(rdcspv::OpConstantNull(outType, editor.MakeId()))));
rdcspv::Id dummyOut = editor.AddConstant(rdcspv::OpConstantComposite(
outType, editor.MakeId(),
{
editor.AddConstantImmediate<float>(1.2f), editor.AddConstantImmediate<float>(3.4f),
editor.AddConstantImmediate<float>(5.6f), editor.AddConstantImmediate<float>(7.8f),
}));
rdcspv::Id breakLabel = editor.MakeId();
rdcspv::Id defaultLabel = editor.MakeId();
func.add(rdcspv::OpStore(outVar, dummyOut));
// combine the operation with the image type:
// operation * 10 + dim
RDCCOMPILE_ASSERT(size_t(ShaderDebugBind::Count) < 10, "Combining value ranges will overlap!");
rdcspv::Id switchVal = func.add(rdcspv::OpIMul(u32, editor.MakeId(), operation,
editor.AddConstantImmediate<uint32_t>(10U)));
switchVal = func.add(rdcspv::OpIAdd(u32, editor.MakeId(), switchVal, dim));
// switch on the combined operation and image type value
rdcarray<rdcspv::PairLiteralIntegerIdRef> targets;
rdcspv::OperationList cases;
rdcspv::Op op;
rdcspv::Id texel_coord[(uint32_t)ShaderDebugBind::Count] = {
rdcspv::Id(),
texel_uv, // 1D - u and array
texel_uvw, // 2D - u,v and array
texel_uvw, // 3D - u,v,w
texel_uvw, // 2DMS - u,v and array
texel_u, // Buffer - u
};
rdcspv::Id coord[(uint32_t)ShaderDebugBind::Count] = {
rdcspv::Id(),
uv, // 1D - u and array
uvw, // 2D - u,v and array
uvw, // 3D - u,v,w
uvw, // 2DMS - u,v and array
u, // Buffer - u
};
rdcspv::Id offsets[(uint32_t)ShaderDebugBind::Count] = {
rdcspv::Id(),
offset_x, // 1D - u
offset_xy, // 2D - u,v
offset_xyz, // 3D - u,v,w
offset_xy, // 2DMS - u,v
offset_x, // Buffer - u
};
uint32_t sampIdx = (uint32_t)ShaderDebugBind::Sampler;
// for(uint32_t i = (uint32_t)ShaderDebugBind::First; i < (uint32_t)ShaderDebugBind::Count; i++)
uint32_t i = (uint32_t)ShaderDebugBind::Tex2D;
{
{
op = rdcspv::Op::ImageFetch;
rdcspv::Id label = editor.MakeId();
targets.push_back({(uint32_t)op * 10 + i, label});
rdcspv::ImageOperandsAndParamDatas imageOperands;
if(i != (uint32_t)ShaderDebugBind::Buffer)
imageOperands.setLod(texel_lod);
cases.add(rdcspv::OpLabel(label));
rdcspv::Id loaded =
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), texSampVars[i]));
rdcspv::Id sampleResult = cases.add(rdcspv::OpImageFetch(
resultType, editor.MakeId(), loaded, texel_coord[i], imageOperands));
cases.add(rdcspv::OpStore(outVar, sampleResult));
cases.add(rdcspv::OpBranch(breakLabel));
}
{
op = rdcspv::Op::ImageSampleExplicitLod;
rdcspv::Id label = editor.MakeId();
targets.push_back({(uint32_t)op * 10 + i, label});
rdcspv::ImageOperandsAndParamDatas imageOperands;
imageOperands.setLod(lod);
imageOperands.setConstOffset(offsets[i]);
cases.add(rdcspv::OpLabel(label));
rdcspv::Id loadedImage =
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), texSampVars[i]));
rdcspv::Id loadedSampler =
cases.add(rdcspv::OpLoad(texSampTypes[sampIdx], editor.MakeId(), texSampVars[sampIdx]));
rdcspv::Id combined = cases.add(rdcspv::OpSampledImage(
texSampCombinedTypes[i], editor.MakeId(), loadedImage, loadedSampler));
rdcspv::Id sampleResult = cases.add(rdcspv::OpImageSampleExplicitLod(
resultType, editor.MakeId(), combined, coord[i], imageOperands));
cases.add(rdcspv::OpStore(outVar, sampleResult));
cases.add(rdcspv::OpBranch(breakLabel));
}
}
func.add(rdcspv::OpSelectionMerge(breakLabel, rdcspv::SelectionControl::None));
func.add(rdcspv::OpSwitch(switchVal, defaultLabel, targets));
func.append(cases);
// default: store NULL data
func.add(rdcspv::OpLabel(defaultLabel));
func.add(rdcspv::OpStore(
outVar, editor.AddConstant(rdcspv::OpConstantNull(resultType, editor.MakeId()))));
func.add(rdcspv::OpBranch(breakLabel));
func.add(rdcspv::OpLabel(breakLabel));
func.add(rdcspv::OpReturn());
func.add(rdcspv::OpFunctionEnd());
+25 -4
View File
@@ -112,10 +112,10 @@ layout(set = 0, binding = 0, std140) uniform constsbuf
vec4 pad4;
} cbuf;
//layout(set = 0, binding = 1) uniform sampler pointSampler;
//layout(set = 0, binding = 2) uniform sampler linearSampler;
layout(set = 0, binding = 1) uniform sampler pointSampler;
layout(set = 0, binding = 2) uniform sampler linearSampler;
//layout(set = 0, binding = 3) uniform texture2D tex;
layout(set = 0, binding = 3) uniform texture2D sampledImage;
//layout(set = 0, binding = 4) uniform sampler2D linearSampledImage;
@@ -151,7 +151,7 @@ void main()
float tiny = linearData.tinyVal;
int intval = int(flatData.intval);
int zerou = int(flatData.intval - flatData.test - 7);
uint zerou = flatData.intval - flatData.test - 7u;
int zeroi = int(zerou);
uint test = flatData.test;
@@ -332,6 +332,27 @@ void main()
cbuf.pad1 + cbuf.pad2 + cbuf.pad3 + cbuf.pad4;
break;
}
case 31:
{
ivec2 coord = ivec2(zeroi + 20, zeroi + 20);
Color = texelFetch(sampledImage, coord, 0);
break;
}
case 32:
{
vec2 coord = vec2(zerof + 0.5, zerof + 0.145);
Color = textureLod(sampler2D(sampledImage, pointSampler), coord, 0.0);
break;
}
case 33:
{
vec2 coord = vec2(zerof + 0.5, zerof + 0.145);
Color = textureLod(sampler2D(sampledImage, linearSampler), coord, 0.0);
break;
}
default: break;
}
}