mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-29 21:30:53 +00:00
Move some shader debug pipeline parameters out of spec constants
* While convenient, passing uv parameters that will probably be different every time via spec constants is not the best idea and will lead to many redundant pipelines. Instead we keep things that must be constant as spec constants as well as a few rarely varying things (texture dimension, operation) while moving more varying things to uniforms passed in a constant buffer. * This means we require the imageGatherExtended feature to promote constant offsets to dynamic offsets, but this is a reasonable requirement.
This commit is contained in:
@@ -207,8 +207,6 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader
|
||||
|
||||
// we plan to support these but needs additional testing/proving
|
||||
|
||||
// image gather operations
|
||||
|
||||
// image storage
|
||||
case Capability::StorageImageMultisample:
|
||||
|
||||
|
||||
@@ -2767,6 +2767,7 @@ void ShaderDebugData::Init(WrappedVulkan *driver, VkDescriptorPool descriptorPoo
|
||||
{4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, NULL},
|
||||
{5, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, NULL},
|
||||
{6, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, NULL},
|
||||
{7, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, NULL},
|
||||
});
|
||||
|
||||
CREATE_OBJECT(PipeLayout, DescSetLayout, sizeof(Vec4f) * 3 + sizeof(uint32_t));
|
||||
@@ -2878,10 +2879,12 @@ void ShaderDebugData::Init(WrappedVulkan *driver, VkDescriptorPool descriptorPoo
|
||||
|
||||
// don't need to ring this, as we hard-sync for readback anyway
|
||||
ReadbackBuffer.Create(driver, driver->GetDev(), sizeof(Vec4f), 1, GPUBuffer::eGPUBufferReadback);
|
||||
ConstantsBuffer.Create(driver, driver->GetDev(), 1024, 1, 0);
|
||||
}
|
||||
|
||||
void ShaderDebugData::Destroy(WrappedVulkan *driver)
|
||||
{
|
||||
ConstantsBuffer.Destroy();
|
||||
ReadbackBuffer.Destroy();
|
||||
|
||||
driver->vkDestroyPipeline(driver->GetDev(), MathPipe, NULL);
|
||||
@@ -2899,4 +2902,7 @@ void ShaderDebugData::Destroy(WrappedVulkan *driver)
|
||||
driver->vkDestroyShaderModule(driver->GetDev(), Module[0], NULL);
|
||||
driver->vkDestroyShaderModule(driver->GetDev(), Module[1], NULL);
|
||||
driver->vkDestroyShaderModule(driver->GetDev(), Module[2], NULL);
|
||||
|
||||
for(auto it = m_Pipelines.begin(); it != m_Pipelines.end(); it++)
|
||||
driver->vkDestroyPipeline(driver->GetDev(), it->second, NULL);
|
||||
}
|
||||
|
||||
@@ -234,6 +234,9 @@ struct ShaderDebugData
|
||||
|
||||
VkShaderModule Module[4] = {};
|
||||
|
||||
std::map<uint32_t, VkPipeline> m_Pipelines;
|
||||
|
||||
GPUBuffer ConstantsBuffer;
|
||||
GPUBuffer ReadbackBuffer;
|
||||
};
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ enum class ShaderDebugBind
|
||||
Tex2DMS,
|
||||
Buffer,
|
||||
Sampler,
|
||||
Constants,
|
||||
Count,
|
||||
};
|
||||
|
||||
@@ -93,12 +94,36 @@ struct GatherOffsets
|
||||
int32_t u0, v0, u1, v1, u2, v2, u3, v3;
|
||||
};
|
||||
|
||||
struct ShaderDebugParameters
|
||||
struct ShaderConstParameters
|
||||
{
|
||||
uint32_t operation;
|
||||
VkBool32 useGrad;
|
||||
VkBool32 useGatherOffsets;
|
||||
VkBool32 useGradOrGatherOffsets;
|
||||
ShaderDebugBind dim;
|
||||
rdcspv::GatherChannel gatherChannel;
|
||||
GatherOffsets gatherOffsets;
|
||||
|
||||
uint32_t hashKey(uint32_t shaderIndex) const
|
||||
{
|
||||
uint32_t hash = 5381;
|
||||
hash = ((hash << 5) + hash) + shaderIndex;
|
||||
hash = ((hash << 5) + hash) + operation;
|
||||
hash = ((hash << 5) + hash) + useGradOrGatherOffsets;
|
||||
hash = ((hash << 5) + hash) + (uint32_t)dim;
|
||||
hash = ((hash << 5) + hash) + (uint32_t)gatherChannel;
|
||||
hash = ((hash << 5) + hash) + gatherOffsets.u0;
|
||||
hash = ((hash << 5) + hash) + gatherOffsets.v0;
|
||||
hash = ((hash << 5) + hash) + gatherOffsets.u1;
|
||||
hash = ((hash << 5) + hash) + gatherOffsets.v1;
|
||||
hash = ((hash << 5) + hash) + gatherOffsets.u2;
|
||||
hash = ((hash << 5) + hash) + gatherOffsets.v2;
|
||||
hash = ((hash << 5) + hash) + gatherOffsets.u3;
|
||||
hash = ((hash << 5) + hash) + gatherOffsets.v3;
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
struct ShaderUniformParameters
|
||||
{
|
||||
Vec3i texel_uvw;
|
||||
int texel_lod;
|
||||
Vec3f uvw;
|
||||
@@ -109,8 +134,6 @@ struct ShaderDebugParameters
|
||||
float compare;
|
||||
float lod;
|
||||
float minlod;
|
||||
rdcspv::GatherChannel gatherChannel;
|
||||
GatherOffsets gatherOffsets;
|
||||
};
|
||||
|
||||
class VulkanAPIWrapper : public rdcspv::DebugAPIWrapper
|
||||
@@ -348,7 +371,8 @@ public:
|
||||
const rdcspv::ImageOperandsAndParamDatas &operands,
|
||||
ShaderVariable &output) override
|
||||
{
|
||||
ShaderDebugParameters params = {};
|
||||
ShaderConstParameters constParams = {};
|
||||
ShaderUniformParameters uniformParams = {};
|
||||
|
||||
const bool buffer = (texType & DebugAPIWrapper::Buffer_Texture) != 0;
|
||||
const bool uintTex = (texType & DebugAPIWrapper::UInt_Texture) != 0;
|
||||
@@ -429,13 +453,13 @@ public:
|
||||
|
||||
switch(imageType)
|
||||
{
|
||||
case VK_IMAGE_TYPE_1D: params.dim = ShaderDebugBind::Tex1D; break;
|
||||
case VK_IMAGE_TYPE_1D: constParams.dim = ShaderDebugBind::Tex1D; break;
|
||||
case VK_IMAGE_TYPE_2D:
|
||||
params.dim = ShaderDebugBind::Tex2D;
|
||||
constParams.dim = ShaderDebugBind::Tex2D;
|
||||
if(samples > 1)
|
||||
params.dim = ShaderDebugBind::Tex2DMS;
|
||||
constParams.dim = ShaderDebugBind::Tex2DMS;
|
||||
break;
|
||||
case VK_IMAGE_TYPE_3D: params.dim = ShaderDebugBind::Tex3D; break;
|
||||
case VK_IMAGE_TYPE_3D: constParams.dim = ShaderDebugBind::Tex3D; break;
|
||||
default:
|
||||
{
|
||||
RDCERR("Unsupported image type %s", ToStr(imageType).c_str());
|
||||
@@ -445,7 +469,7 @@ public:
|
||||
|
||||
if(buffer)
|
||||
{
|
||||
params.dim = ShaderDebugBind::Buffer;
|
||||
constParams.dim = ShaderDebugBind::Buffer;
|
||||
coords = gradCoords = 1;
|
||||
}
|
||||
|
||||
@@ -588,7 +612,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
params.operation = (uint32_t)opcode;
|
||||
constParams.operation = (uint32_t)opcode;
|
||||
|
||||
// proj opcodes have an extra q parameter
|
||||
switch(opcode)
|
||||
@@ -626,74 +650,72 @@ public:
|
||||
{
|
||||
// co-ordinates after the used ones are read as 0s. This allows us to then read an implicit
|
||||
// 0 for array layer when we promote accesses to arrays.
|
||||
params.texel_uvw.x = uv.value.u.x;
|
||||
uniformParams.texel_uvw.x = uv.value.u.x;
|
||||
if(coords >= 2)
|
||||
params.texel_uvw.y = uv.value.u.y;
|
||||
uniformParams.texel_uvw.y = uv.value.u.y;
|
||||
if(coords >= 3)
|
||||
params.texel_uvw.z = uv.value.u.z;
|
||||
uniformParams.texel_uvw.z = uv.value.u.z;
|
||||
|
||||
if(!buffer && operands.flags & rdcspv::ImageOperands::Lod)
|
||||
params.texel_lod = lane.GetSrc(operands.lod).value.i.x;
|
||||
uniformParams.texel_lod = lane.GetSrc(operands.lod).value.i.x;
|
||||
else
|
||||
params.texel_lod = 0;
|
||||
uniformParams.texel_lod = 0;
|
||||
|
||||
if(operands.flags & rdcspv::ImageOperands::Sample)
|
||||
params.sampleIdx = lane.GetSrc(operands.sample).value.u.x;
|
||||
uniformParams.sampleIdx = lane.GetSrc(operands.sample).value.u.x;
|
||||
|
||||
break;
|
||||
}
|
||||
case rdcspv::Op::ImageGather:
|
||||
case rdcspv::Op::ImageDrefGather:
|
||||
{
|
||||
params.uvw.x = uv.value.f.x;
|
||||
uniformParams.uvw.x = uv.value.f.x;
|
||||
if(coords >= 2)
|
||||
params.uvw.y = uv.value.f.y;
|
||||
uniformParams.uvw.y = uv.value.f.y;
|
||||
if(coords >= 3)
|
||||
params.uvw.z = uv.value.f.z;
|
||||
uniformParams.uvw.z = uv.value.f.z;
|
||||
|
||||
if(useCompare)
|
||||
params.compare = compare.value.f.x;
|
||||
uniformParams.compare = compare.value.f.x;
|
||||
|
||||
params.gatherChannel = gatherChannel;
|
||||
constParams.gatherChannel = gatherChannel;
|
||||
|
||||
if(operands.flags & rdcspv::ImageOperands::ConstOffsets)
|
||||
{
|
||||
ShaderVariable constOffsets = lane.GetSrc(operands.constOffsets);
|
||||
|
||||
params.useGatherOffsets = VK_TRUE;
|
||||
constParams.useGradOrGatherOffsets = VK_TRUE;
|
||||
|
||||
// should be an array of ivec2
|
||||
RDCASSERT(constOffsets.members.size() == 4);
|
||||
|
||||
params.gatherOffsets.u0 = constOffsets.members[0].value.i.x;
|
||||
params.gatherOffsets.v0 = constOffsets.members[0].value.i.y;
|
||||
params.gatherOffsets.u1 = constOffsets.members[1].value.i.x;
|
||||
params.gatherOffsets.v1 = constOffsets.members[1].value.i.y;
|
||||
params.gatherOffsets.u2 = constOffsets.members[1].value.i.x;
|
||||
params.gatherOffsets.v2 = constOffsets.members[1].value.i.y;
|
||||
params.gatherOffsets.u3 = constOffsets.members[1].value.i.x;
|
||||
params.gatherOffsets.v3 = constOffsets.members[1].value.i.y;
|
||||
constParams.gatherOffsets.u0 = constOffsets.members[0].value.i.x;
|
||||
constParams.gatherOffsets.v0 = constOffsets.members[0].value.i.y;
|
||||
constParams.gatherOffsets.u1 = constOffsets.members[1].value.i.x;
|
||||
constParams.gatherOffsets.v1 = constOffsets.members[1].value.i.y;
|
||||
constParams.gatherOffsets.u2 = constOffsets.members[1].value.i.x;
|
||||
constParams.gatherOffsets.v2 = constOffsets.members[1].value.i.y;
|
||||
constParams.gatherOffsets.u3 = constOffsets.members[1].value.i.x;
|
||||
constParams.gatherOffsets.v3 = constOffsets.members[1].value.i.y;
|
||||
}
|
||||
|
||||
params.useGatherOffsets = VK_FALSE;
|
||||
|
||||
if(operands.flags & rdcspv::ImageOperands::ConstOffset)
|
||||
{
|
||||
ShaderVariable constOffset = lane.GetSrc(operands.constOffset);
|
||||
params.offset.x = constOffset.value.i.x;
|
||||
uniformParams.offset.x = constOffset.value.i.x;
|
||||
if(gradCoords >= 2)
|
||||
params.offset.y = constOffset.value.i.y;
|
||||
uniformParams.offset.y = constOffset.value.i.y;
|
||||
if(gradCoords >= 3)
|
||||
params.offset.z = constOffset.value.i.z;
|
||||
uniformParams.offset.z = constOffset.value.i.z;
|
||||
}
|
||||
else if(operands.flags & rdcspv::ImageOperands::Offset)
|
||||
{
|
||||
ShaderVariable offset = lane.GetSrc(operands.offset);
|
||||
params.offset.x = offset.value.i.x;
|
||||
uniformParams.offset.x = offset.value.i.x;
|
||||
if(gradCoords >= 2)
|
||||
params.offset.y = offset.value.i.y;
|
||||
uniformParams.offset.y = offset.value.i.y;
|
||||
if(gradCoords >= 3)
|
||||
params.offset.z = offset.value.i.z;
|
||||
uniformParams.offset.z = offset.value.i.z;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -707,79 +729,79 @@ public:
|
||||
case rdcspv::Op::ImageSampleProjDrefExplicitLod:
|
||||
case rdcspv::Op::ImageSampleProjDrefImplicitLod:
|
||||
{
|
||||
params.uvw.x = uv.value.f.x;
|
||||
uniformParams.uvw.x = uv.value.f.x;
|
||||
if(coords >= 2)
|
||||
params.uvw.y = uv.value.f.y;
|
||||
uniformParams.uvw.y = uv.value.f.y;
|
||||
if(coords >= 3)
|
||||
params.uvw.z = uv.value.f.z;
|
||||
uniformParams.uvw.z = uv.value.f.z;
|
||||
|
||||
if(operands.flags & rdcspv::ImageOperands::MinLod)
|
||||
params.minlod = lane.GetSrc(operands.minLod).value.f.x;
|
||||
uniformParams.minlod = lane.GetSrc(operands.minLod).value.f.x;
|
||||
|
||||
if(useCompare)
|
||||
params.compare = compare.value.f.x;
|
||||
uniformParams.compare = compare.value.f.x;
|
||||
|
||||
if(operands.flags & rdcspv::ImageOperands::Lod)
|
||||
{
|
||||
params.lod = lane.GetSrc(operands.lod).value.f.x;
|
||||
params.useGrad = VK_FALSE;
|
||||
uniformParams.lod = lane.GetSrc(operands.lod).value.f.x;
|
||||
constParams.useGradOrGatherOffsets = VK_FALSE;
|
||||
}
|
||||
else if(operands.flags & rdcspv::ImageOperands::Grad)
|
||||
{
|
||||
ShaderVariable ddx = lane.GetSrc(operands.grad.first);
|
||||
ShaderVariable ddy = lane.GetSrc(operands.grad.second);
|
||||
|
||||
params.useGrad = VK_TRUE;
|
||||
constParams.useGradOrGatherOffsets = VK_TRUE;
|
||||
|
||||
params.ddx.x = ddx.value.f.x;
|
||||
uniformParams.ddx.x = ddx.value.f.x;
|
||||
if(gradCoords >= 2)
|
||||
params.ddx.y = ddx.value.f.y;
|
||||
uniformParams.ddx.y = ddx.value.f.y;
|
||||
if(gradCoords >= 3)
|
||||
params.ddx.z = ddx.value.f.z;
|
||||
uniformParams.ddx.z = ddx.value.f.z;
|
||||
|
||||
params.ddy.x = ddy.value.f.x;
|
||||
uniformParams.ddy.x = ddy.value.f.x;
|
||||
if(gradCoords >= 2)
|
||||
params.ddy.y = ddy.value.f.y;
|
||||
uniformParams.ddy.y = ddy.value.f.y;
|
||||
if(gradCoords >= 3)
|
||||
params.ddy.z = ddy.value.f.z;
|
||||
uniformParams.ddy.z = ddy.value.f.z;
|
||||
}
|
||||
|
||||
if(opcode == rdcspv::Op::ImageSampleImplicitLod ||
|
||||
opcode == rdcspv::Op::ImageSampleProjImplicitLod)
|
||||
{
|
||||
// use grad to sub in for the implicit lod
|
||||
params.useGrad = VK_TRUE;
|
||||
constParams.useGradOrGatherOffsets = VK_TRUE;
|
||||
|
||||
params.ddx.x = ddxCalc.value.f.x;
|
||||
uniformParams.ddx.x = ddxCalc.value.f.x;
|
||||
if(gradCoords >= 2)
|
||||
params.ddx.y = ddxCalc.value.f.y;
|
||||
uniformParams.ddx.y = ddxCalc.value.f.y;
|
||||
if(gradCoords >= 3)
|
||||
params.ddx.z = ddxCalc.value.f.z;
|
||||
uniformParams.ddx.z = ddxCalc.value.f.z;
|
||||
|
||||
params.ddy.x = ddyCalc.value.f.x;
|
||||
uniformParams.ddy.x = ddyCalc.value.f.x;
|
||||
if(gradCoords >= 2)
|
||||
params.ddy.y = ddyCalc.value.f.y;
|
||||
uniformParams.ddy.y = ddyCalc.value.f.y;
|
||||
if(gradCoords >= 3)
|
||||
params.ddy.z = ddyCalc.value.f.z;
|
||||
uniformParams.ddy.z = ddyCalc.value.f.z;
|
||||
}
|
||||
|
||||
if(operands.flags & rdcspv::ImageOperands::ConstOffset)
|
||||
{
|
||||
ShaderVariable constOffset = lane.GetSrc(operands.constOffset);
|
||||
params.offset.x = constOffset.value.i.x;
|
||||
uniformParams.offset.x = constOffset.value.i.x;
|
||||
if(gradCoords >= 2)
|
||||
params.offset.y = constOffset.value.i.y;
|
||||
uniformParams.offset.y = constOffset.value.i.y;
|
||||
if(gradCoords >= 3)
|
||||
params.offset.z = constOffset.value.i.z;
|
||||
uniformParams.offset.z = constOffset.value.i.z;
|
||||
}
|
||||
else if(operands.flags & rdcspv::ImageOperands::Offset)
|
||||
{
|
||||
ShaderVariable offset = lane.GetSrc(operands.offset);
|
||||
params.offset.x = offset.value.i.x;
|
||||
uniformParams.offset.x = offset.value.i.x;
|
||||
if(gradCoords >= 2)
|
||||
params.offset.y = offset.value.i.y;
|
||||
uniformParams.offset.y = offset.value.i.y;
|
||||
if(gradCoords >= 3)
|
||||
params.offset.z = offset.value.i.z;
|
||||
uniformParams.offset.z = offset.value.i.z;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -791,16 +813,39 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
VkPipeline pipe = MakePipe(params, uintTex, sintTex);
|
||||
// we don't support constant offsets, they're always promoted to dynamic offsets to avoid
|
||||
// needing to potentially compile lots of pipelines with different offsets. If we're actually
|
||||
// using them and the device doesn't support the extended gather feature, the result will be
|
||||
// wrong.
|
||||
if(!m_pDriver->GetDeviceFeatures().shaderImageGatherExtended &&
|
||||
(uniformParams.offset.x != 0 || uniformParams.offset.y != 0 || uniformParams.offset.z != 0))
|
||||
{
|
||||
m_pDriver->AddDebugMessage(
|
||||
MessageCategory::Execution, MessageSeverity::High, MessageSource::RuntimeWarning,
|
||||
StringFormat::Fmt("Use of constant offsets %d/%d/%d is not supported without "
|
||||
"shaderImageGatherExtended device feature",
|
||||
uniformParams.offset.x, uniformParams.offset.y, uniformParams.offset.z));
|
||||
}
|
||||
|
||||
VkPipeline pipe = MakePipe(constParams, uintTex, sintTex);
|
||||
|
||||
VkDescriptorImageInfo samplerWriteInfo = {Unwrap(sampler), VK_NULL_HANDLE,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED};
|
||||
VkDescriptorImageInfo imageWriteInfo = {VK_NULL_HANDLE, Unwrap(sampleView), layout};
|
||||
|
||||
VkDescriptorBufferInfo uniformWriteInfo = {};
|
||||
m_DebugData.ConstantsBuffer.FillDescriptor(uniformWriteInfo);
|
||||
|
||||
VkWriteDescriptorSet writeSets[] = {
|
||||
{
|
||||
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_DebugData.DescSet),
|
||||
(uint32_t)params.dim, 0, 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageWriteInfo, NULL, NULL,
|
||||
(uint32_t)ShaderDebugBind::Constants, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, NULL,
|
||||
&uniformWriteInfo, NULL,
|
||||
},
|
||||
{
|
||||
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_DebugData.DescSet),
|
||||
(uint32_t)constParams.dim, 0, 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageWriteInfo,
|
||||
NULL, NULL,
|
||||
},
|
||||
{
|
||||
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_DebugData.DescSet),
|
||||
@@ -811,13 +856,19 @@ public:
|
||||
|
||||
if(buffer)
|
||||
{
|
||||
writeSets[0].pTexelBufferView = UnwrapPtr(bufferView);
|
||||
writeSets[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
||||
writeSets[1].pTexelBufferView = UnwrapPtr(bufferView);
|
||||
writeSets[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
||||
}
|
||||
|
||||
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), sampler != VK_NULL_HANDLE ? 2 : 1, writeSets, 0,
|
||||
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), sampler != VK_NULL_HANDLE ? 3 : 2, writeSets, 0,
|
||||
NULL);
|
||||
|
||||
void *constants = m_DebugData.ConstantsBuffer.Map(NULL, 0);
|
||||
|
||||
memcpy(constants, &uniformParams, sizeof(uniformParams));
|
||||
|
||||
m_DebugData.ConstantsBuffer.Unmap();
|
||||
|
||||
{
|
||||
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
|
||||
|
||||
@@ -863,8 +914,6 @@ public:
|
||||
m_pDriver->FlushQ();
|
||||
}
|
||||
|
||||
m_pDriver->vkDestroyPipeline(dev, pipe, NULL);
|
||||
|
||||
Vec4f *ret = (Vec4f *)m_DebugData.ReadbackBuffer.Map(NULL, 0);
|
||||
|
||||
memcpy(output.value.uv, ret, sizeof(Vec4f));
|
||||
@@ -881,7 +930,7 @@ public:
|
||||
|
||||
if(m_DebugData.MathPipe == VK_NULL_HANDLE)
|
||||
{
|
||||
ShaderDebugParameters pipeParams = {};
|
||||
ShaderConstParameters pipeParams = {};
|
||||
pipeParams.operation = (uint32_t)rdcspv::Op::ExtInst;
|
||||
m_DebugData.MathPipe = MakePipe(pipeParams, false, false);
|
||||
}
|
||||
@@ -1035,7 +1084,7 @@ private:
|
||||
return elemData[index.arrayIndex];
|
||||
}
|
||||
|
||||
VkPipeline MakePipe(const ShaderDebugParameters ¶ms, bool uintTex, bool sintTex)
|
||||
VkPipeline MakePipe(const ShaderConstParameters ¶ms, bool uintTex, bool sintTex)
|
||||
{
|
||||
VkSpecializationMapEntry specMaps[sizeof(params) / sizeof(uint32_t)];
|
||||
for(size_t i = 0; i < ARRAY_COUNT(specMaps); i++)
|
||||
@@ -1086,6 +1135,17 @@ private:
|
||||
FileIO::WriteAll(Vulkan_Debug_PSDebugDumpDirPath + filename[shaderIndex], spirv);
|
||||
}
|
||||
|
||||
uint32_t key = params.hashKey(shaderIndex);
|
||||
|
||||
if(m_DebugData.m_Pipelines[key] != VK_NULL_HANDLE)
|
||||
return m_DebugData.m_Pipelines[key];
|
||||
|
||||
RDCLOG(
|
||||
"Making new pipeline for shader type %u, operation %s, dim %u, useGrad/useGatherOffsets %u,"
|
||||
" gather channel %u, gather offsets...",
|
||||
shaderIndex, ToStr((rdcspv::Op)params.operation).c_str(), params.dim,
|
||||
params.useGradOrGatherOffsets, params.gatherChannel);
|
||||
|
||||
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},
|
||||
@@ -1179,6 +1239,8 @@ private:
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
m_DebugData.m_Pipelines[key] = pipe;
|
||||
|
||||
return pipe;
|
||||
}
|
||||
|
||||
@@ -1438,36 +1500,16 @@ private:
|
||||
rdcspv::Id scalarResultType = editor.DeclareType(base);
|
||||
|
||||
// add specialisation constants for all the parameters
|
||||
#define SPEC_ID(name) uint32_t(offsetof(ShaderDebugParameters, name) / sizeof(uint32_t))
|
||||
#define MEMBER_IDX(struct, name) uint32_t(offsetof(struct, name) / sizeof(uint32_t))
|
||||
|
||||
#define DECL_SPECID(type, name, value) \
|
||||
rdcspv::Id name = editor.AddSpecConstantImmediate<type>(0U, SPEC_ID(value)); \
|
||||
#define DECL_SPECID(type, name, value) \
|
||||
rdcspv::Id name = \
|
||||
editor.AddSpecConstantImmediate<type>(0U, MEMBER_IDX(ShaderConstParameters, value)); \
|
||||
editor.SetName(name, "spec_" #name);
|
||||
|
||||
DECL_SPECID(uint32_t, operation, operation);
|
||||
DECL_SPECID(bool, useGrad, useGrad);
|
||||
DECL_SPECID(bool, useGatherOffsets, useGatherOffsets);
|
||||
DECL_SPECID(bool, useGradOrGatherOffsets, useGradOrGatherOffsets);
|
||||
DECL_SPECID(uint32_t, dim, dim);
|
||||
DECL_SPECID(int32_t, texel_u, texel_uvw.x);
|
||||
DECL_SPECID(int32_t, texel_v, texel_uvw.y);
|
||||
DECL_SPECID(int32_t, texel_w, texel_uvw.z);
|
||||
DECL_SPECID(int32_t, texel_lod, texel_lod);
|
||||
DECL_SPECID(float, u, uvw.x);
|
||||
DECL_SPECID(float, v, uvw.y);
|
||||
DECL_SPECID(float, w, uvw.z);
|
||||
DECL_SPECID(float, dudx, ddx.x);
|
||||
DECL_SPECID(float, dvdx, ddx.y);
|
||||
DECL_SPECID(float, dwdx, ddx.z);
|
||||
DECL_SPECID(float, dudy, ddy.x);
|
||||
DECL_SPECID(float, dvdy, ddy.y);
|
||||
DECL_SPECID(float, dwdy, ddy.z);
|
||||
DECL_SPECID(int32_t, offset_x, offset.x);
|
||||
DECL_SPECID(int32_t, offset_y, offset.y);
|
||||
DECL_SPECID(int32_t, offset_z, offset.z);
|
||||
DECL_SPECID(int32_t, sampleIdx, sampleIdx);
|
||||
DECL_SPECID(float, compare, compare);
|
||||
DECL_SPECID(float, lod, lod);
|
||||
DECL_SPECID(float, minlod, minlod);
|
||||
DECL_SPECID(int32_t, gatherChannel, gatherChannel);
|
||||
DECL_SPECID(int32_t, gather_u0, gatherOffsets.u0);
|
||||
DECL_SPECID(int32_t, gather_v0, gatherOffsets.v0);
|
||||
@@ -1478,45 +1520,62 @@ private:
|
||||
DECL_SPECID(int32_t, gather_u3, gatherOffsets.u3);
|
||||
DECL_SPECID(int32_t, gather_v3, gatherOffsets.v3);
|
||||
|
||||
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}));
|
||||
struct StructMember
|
||||
{
|
||||
rdcspv::Id loadedType;
|
||||
rdcspv::Id ptrType;
|
||||
rdcspv::Id loadedId;
|
||||
const char *name;
|
||||
uint32_t memberIndex;
|
||||
};
|
||||
|
||||
editor.SetName(texel_uv, "texel_uv");
|
||||
editor.SetName(texel_uvw, "texel_uvw");
|
||||
rdcarray<rdcspv::Id> memberIds;
|
||||
rdcarray<StructMember> cbufferMembers;
|
||||
|
||||
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 type_int32_t = editor.DeclareType(rdcspv::scalar<int32_t>());
|
||||
rdcspv::Id type_float = editor.DeclareType(rdcspv::scalar<float>());
|
||||
|
||||
editor.SetName(uv, "uv");
|
||||
editor.SetName(uvw, "uvw");
|
||||
rdcspv::Id uniformptr_int32_t =
|
||||
editor.DeclareType(rdcspv::Pointer(type_int32_t, rdcspv::StorageClass::Uniform));
|
||||
rdcspv::Id uniformptr_float =
|
||||
editor.DeclareType(rdcspv::Pointer(type_float, rdcspv::StorageClass::Uniform));
|
||||
|
||||
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}));
|
||||
#define DECL_UNIFORM(type, name, value) \
|
||||
rdcspv::Id name = editor.MakeId(); \
|
||||
editor.SetName(name, "uniform_" #name); \
|
||||
cbufferMembers.push_back({CONCAT(type_, type), CONCAT(uniformptr_, type), name, #name, \
|
||||
MEMBER_IDX(ShaderUniformParameters, value)}); \
|
||||
memberIds.push_back(CONCAT(type_, type));
|
||||
DECL_UNIFORM(int32_t, texel_u, texel_uvw.x);
|
||||
DECL_UNIFORM(int32_t, texel_v, texel_uvw.y);
|
||||
DECL_UNIFORM(int32_t, texel_w, texel_uvw.z);
|
||||
DECL_UNIFORM(int32_t, texel_lod, texel_lod);
|
||||
DECL_UNIFORM(float, u, uvw.x);
|
||||
DECL_UNIFORM(float, v, uvw.y);
|
||||
DECL_UNIFORM(float, w, uvw.z);
|
||||
DECL_UNIFORM(float, dudx, ddx.x);
|
||||
DECL_UNIFORM(float, dvdx, ddx.y);
|
||||
DECL_UNIFORM(float, dwdx, ddx.z);
|
||||
DECL_UNIFORM(float, dudy, ddy.x);
|
||||
DECL_UNIFORM(float, dvdy, ddy.y);
|
||||
DECL_UNIFORM(float, dwdy, ddy.z);
|
||||
DECL_UNIFORM(int32_t, offset_x, offset.x);
|
||||
DECL_UNIFORM(int32_t, offset_y, offset.y);
|
||||
DECL_UNIFORM(int32_t, offset_z, offset.z);
|
||||
DECL_UNIFORM(int32_t, sampleIdx, sampleIdx);
|
||||
DECL_UNIFORM(float, compare, compare);
|
||||
DECL_UNIFORM(float, lod, lod);
|
||||
DECL_UNIFORM(float, minlod, minlod);
|
||||
|
||||
editor.SetName(ddx_uv, "ddx_uv");
|
||||
editor.SetName(ddx_uvw, "ddx_uvw");
|
||||
|
||||
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}));
|
||||
|
||||
editor.SetName(ddy_uv, "ddy_uv");
|
||||
editor.SetName(ddy_uvw, "ddy_uvw");
|
||||
|
||||
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}));
|
||||
|
||||
editor.SetName(offset_xy, "offset_xy");
|
||||
editor.SetName(offset_xyz, "offset_xyz");
|
||||
rdcspv::Id cbufferStructID = editor.AddType(rdcspv::OpTypeStruct(editor.MakeId(), memberIds));
|
||||
editor.AddDecoration(rdcspv::OpDecorate(cbufferStructID, rdcspv::Decoration::Block));
|
||||
for(const StructMember &m : cbufferMembers)
|
||||
{
|
||||
editor.AddDecoration(rdcspv::OpMemberDecorate(
|
||||
cbufferStructID, m.memberIndex,
|
||||
rdcspv::DecorationParam<rdcspv::Decoration::Offset>(m.memberIndex * sizeof(uint32_t))));
|
||||
editor.SetMemberName(cbufferStructID, m.memberIndex, m.name);
|
||||
}
|
||||
|
||||
rdcspv::Id gather_0 = editor.AddConstant(
|
||||
rdcspv::OpSpecConstantComposite(v2i32, editor.MakeId(), {gather_u0, gather_v0}));
|
||||
@@ -1554,8 +1613,9 @@ private:
|
||||
editor.DeclareType(rdcspv::Image(base, rdcspv::Dim::_2D, 0, 1, 1, 1, unk)),
|
||||
editor.DeclareType(rdcspv::Image(base, rdcspv::Dim::Buffer, 0, 0, 0, 1, unk)),
|
||||
editor.DeclareType(rdcspv::Sampler()),
|
||||
cbufferStructID,
|
||||
};
|
||||
rdcspv::Id texSampVars[(uint32_t)ShaderDebugBind::Count];
|
||||
rdcspv::Id bindVars[(uint32_t)ShaderDebugBind::Count];
|
||||
rdcspv::Id texSampCombinedTypes[(uint32_t)ShaderDebugBind::Count] = {
|
||||
rdcspv::Id(),
|
||||
editor.DeclareType(rdcspv::SampledImage(texSampTypes[1])),
|
||||
@@ -1564,30 +1624,33 @@ private:
|
||||
editor.DeclareType(rdcspv::SampledImage(texSampTypes[4])),
|
||||
editor.DeclareType(rdcspv::SampledImage(texSampTypes[5])),
|
||||
rdcspv::Id(),
|
||||
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));
|
||||
rdcspv::StorageClass storageClass = rdcspv::StorageClass::UniformConstant;
|
||||
|
||||
texSampVars[i] = editor.AddVariable(
|
||||
rdcspv::OpVariable(ptrType, editor.MakeId(), rdcspv::StorageClass::UniformConstant));
|
||||
if(i == (size_t)ShaderDebugBind::Constants)
|
||||
storageClass = rdcspv::StorageClass::Uniform;
|
||||
|
||||
rdcspv::Id ptrType = editor.DeclareType(rdcspv::Pointer(texSampTypes[i], storageClass));
|
||||
|
||||
bindVars[i] = editor.AddVariable(rdcspv::OpVariable(ptrType, editor.MakeId(), storageClass));
|
||||
|
||||
editor.AddDecoration(rdcspv::OpDecorate(
|
||||
texSampVars[i], rdcspv::DecorationParam<rdcspv::Decoration::DescriptorSet>(0U)));
|
||||
bindVars[i], rdcspv::DecorationParam<rdcspv::Decoration::DescriptorSet>(0U)));
|
||||
editor.AddDecoration(rdcspv::OpDecorate(
|
||||
texSampVars[i], rdcspv::DecorationParam<rdcspv::Decoration::Binding>((uint32_t)i)));
|
||||
bindVars[i], rdcspv::DecorationParam<rdcspv::Decoration::Binding>((uint32_t)i)));
|
||||
}
|
||||
|
||||
editor.SetName(texSampVars[(size_t)ShaderDebugBind::Tex1D], "Tex1D");
|
||||
editor.SetName(texSampVars[(size_t)ShaderDebugBind::Tex2D], "Tex2D");
|
||||
editor.SetName(texSampVars[(size_t)ShaderDebugBind::Tex3D], "Tex3D");
|
||||
editor.SetName(texSampVars[(size_t)ShaderDebugBind::Tex2DMS], "Tex2DMS");
|
||||
editor.SetName(texSampVars[(size_t)ShaderDebugBind::Buffer], "Buffer");
|
||||
editor.SetName(texSampVars[(size_t)ShaderDebugBind::Sampler], "Sampler");
|
||||
|
||||
rdcspv::Id sampVar = texSampVars[(size_t)ShaderDebugBind::Sampler];
|
||||
editor.SetName(bindVars[(size_t)ShaderDebugBind::Tex1D], "Tex1D");
|
||||
editor.SetName(bindVars[(size_t)ShaderDebugBind::Tex2D], "Tex2D");
|
||||
editor.SetName(bindVars[(size_t)ShaderDebugBind::Tex3D], "Tex3D");
|
||||
editor.SetName(bindVars[(size_t)ShaderDebugBind::Tex2DMS], "Tex2DMS");
|
||||
editor.SetName(bindVars[(size_t)ShaderDebugBind::Buffer], "Buffer");
|
||||
editor.SetName(bindVars[(size_t)ShaderDebugBind::Sampler], "Sampler");
|
||||
editor.SetName(bindVars[(size_t)ShaderDebugBind::Constants], "CBuffer");
|
||||
|
||||
// register the entry point
|
||||
editor.AddOperation(
|
||||
@@ -1603,6 +1666,52 @@ private:
|
||||
func.add(rdcspv::OpFunction(voidType, entryId, rdcspv::FunctionControl::None, funcType));
|
||||
func.add(rdcspv::OpLabel(editor.MakeId()));
|
||||
|
||||
// access chain and load all the cbuffer variables
|
||||
for(const StructMember &m : cbufferMembers)
|
||||
{
|
||||
rdcspv::Id ptr = func.add(rdcspv::OpAccessChain(
|
||||
m.ptrType, editor.MakeId(), bindVars[(size_t)ShaderDebugBind::Constants],
|
||||
{editor.AddConstantImmediate<uint32_t>(m.memberIndex)}));
|
||||
func.add(rdcspv::OpLoad(m.loadedType, m.loadedId, ptr));
|
||||
}
|
||||
|
||||
// declare cbuffer composites
|
||||
rdcspv::Id texel_uv =
|
||||
func.add(rdcspv::OpCompositeConstruct(v2i32, editor.MakeId(), {texel_u, texel_v}));
|
||||
rdcspv::Id texel_uvw =
|
||||
func.add(rdcspv::OpCompositeConstruct(v3i32, editor.MakeId(), {texel_u, texel_v, texel_w}));
|
||||
|
||||
editor.SetName(texel_uv, "texel_uv");
|
||||
editor.SetName(texel_uvw, "texel_uvw");
|
||||
|
||||
rdcspv::Id uv = func.add(rdcspv::OpCompositeConstruct(v2f32, editor.MakeId(), {u, v}));
|
||||
rdcspv::Id uvw = func.add(rdcspv::OpCompositeConstruct(v3f32, editor.MakeId(), {u, v, w}));
|
||||
|
||||
editor.SetName(uv, "uv");
|
||||
editor.SetName(uvw, "uvw");
|
||||
|
||||
rdcspv::Id ddx_uv = func.add(rdcspv::OpCompositeConstruct(v2f32, editor.MakeId(), {dudx, dvdx}));
|
||||
rdcspv::Id ddx_uvw =
|
||||
func.add(rdcspv::OpCompositeConstruct(v3f32, editor.MakeId(), {dudx, dvdx, dwdx}));
|
||||
|
||||
editor.SetName(ddx_uv, "ddx_uv");
|
||||
editor.SetName(ddx_uvw, "ddx_uvw");
|
||||
|
||||
rdcspv::Id ddy_uv = func.add(rdcspv::OpCompositeConstruct(v2f32, editor.MakeId(), {dudy, dvdy}));
|
||||
rdcspv::Id ddy_uvw =
|
||||
func.add(rdcspv::OpCompositeConstruct(v3f32, editor.MakeId(), {dudy, dvdy, dwdy}));
|
||||
|
||||
editor.SetName(ddy_uv, "ddy_uv");
|
||||
editor.SetName(ddy_uvw, "ddy_uvw");
|
||||
|
||||
rdcspv::Id offset_xy =
|
||||
func.add(rdcspv::OpCompositeConstruct(v2i32, editor.MakeId(), {offset_x, offset_y}));
|
||||
rdcspv::Id offset_xyz = func.add(
|
||||
rdcspv::OpCompositeConstruct(v3i32, editor.MakeId(), {offset_x, offset_y, offset_z}));
|
||||
|
||||
editor.SetName(offset_xy, "offset_xy");
|
||||
editor.SetName(offset_xyz, "offset_xyz");
|
||||
|
||||
// first store NULL data in, so the output is always initialised
|
||||
|
||||
rdcspv::Id breakLabel = editor.MakeId();
|
||||
@@ -1673,7 +1782,7 @@ private:
|
||||
|
||||
for(uint32_t i = (uint32_t)ShaderDebugBind::First; i < (uint32_t)ShaderDebugBind::Count; i++)
|
||||
{
|
||||
if(i == sampIdx)
|
||||
if(i == sampIdx || i == (uint32_t)ShaderDebugBind::Constants)
|
||||
continue;
|
||||
|
||||
{
|
||||
@@ -1691,8 +1800,7 @@ private:
|
||||
imageOperands.setSample(sampleIdx);
|
||||
|
||||
cases.add(rdcspv::OpLabel(label));
|
||||
rdcspv::Id loaded =
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), texSampVars[i]));
|
||||
rdcspv::Id loaded = cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), bindVars[i]));
|
||||
rdcspv::Id sampleResult = cases.add(rdcspv::OpImageFetch(
|
||||
resultType, editor.MakeId(), loaded, texel_coord[i], imageOperands));
|
||||
cases.add(rdcspv::OpStore(outVar, sampleResult));
|
||||
@@ -1711,19 +1819,20 @@ private:
|
||||
|
||||
rdcspv::ImageOperandsAndParamDatas imageOperands;
|
||||
|
||||
imageOperands.setConstOffset(offsets[i]);
|
||||
if(m_pDriver->GetDeviceFeatures().shaderImageGatherExtended)
|
||||
imageOperands.setOffset(offsets[i]);
|
||||
|
||||
cases.add(rdcspv::OpLabel(label));
|
||||
rdcspv::Id loadedImage =
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), texSampVars[i]));
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), bindVars[i]));
|
||||
rdcspv::Id loadedSampler =
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[sampIdx], editor.MakeId(), texSampVars[sampIdx]));
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[sampIdx], editor.MakeId(), bindVars[sampIdx]));
|
||||
|
||||
rdcspv::Id mergeLabel = editor.MakeId();
|
||||
rdcspv::Id gradCase = editor.MakeId();
|
||||
rdcspv::Id lodCase = editor.MakeId();
|
||||
cases.add(rdcspv::OpSelectionMerge(mergeLabel, rdcspv::SelectionControl::None));
|
||||
cases.add(rdcspv::OpBranchConditional(useGrad, gradCase, lodCase));
|
||||
cases.add(rdcspv::OpBranchConditional(useGradOrGatherOffsets, gradCase, lodCase));
|
||||
|
||||
rdcspv::Id lodResult;
|
||||
{
|
||||
@@ -1778,19 +1887,20 @@ private:
|
||||
|
||||
rdcspv::ImageOperandsAndParamDatas imageOperands;
|
||||
|
||||
imageOperands.setConstOffset(offsets[i]);
|
||||
if(m_pDriver->GetDeviceFeatures().shaderImageGatherExtended)
|
||||
imageOperands.setOffset(offsets[i]);
|
||||
|
||||
cases.add(rdcspv::OpLabel(label));
|
||||
rdcspv::Id loadedImage =
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), texSampVars[i]));
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), bindVars[i]));
|
||||
rdcspv::Id loadedSampler =
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[sampIdx], editor.MakeId(), texSampVars[sampIdx]));
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[sampIdx], editor.MakeId(), bindVars[sampIdx]));
|
||||
|
||||
rdcspv::Id mergeLabel = editor.MakeId();
|
||||
rdcspv::Id gradCase = editor.MakeId();
|
||||
rdcspv::Id lodCase = editor.MakeId();
|
||||
cases.add(rdcspv::OpSelectionMerge(mergeLabel, rdcspv::SelectionControl::None));
|
||||
cases.add(rdcspv::OpBranchConditional(useGrad, gradCase, lodCase));
|
||||
cases.add(rdcspv::OpBranchConditional(useGradOrGatherOffsets, gradCase, lodCase));
|
||||
|
||||
rdcspv::Id lodResult;
|
||||
{
|
||||
@@ -1854,9 +1964,9 @@ private:
|
||||
|
||||
cases.add(rdcspv::OpLabel(label));
|
||||
rdcspv::Id loadedImage =
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), texSampVars[i]));
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), bindVars[i]));
|
||||
rdcspv::Id loadedSampler =
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[sampIdx], editor.MakeId(), texSampVars[sampIdx]));
|
||||
cases.add(rdcspv::OpLoad(texSampTypes[sampIdx], editor.MakeId(), bindVars[sampIdx]));
|
||||
|
||||
rdcspv::Id sampleResult;
|
||||
if(m_pDriver->GetDeviceFeatures().shaderImageGatherExtended)
|
||||
@@ -1865,13 +1975,16 @@ private:
|
||||
rdcspv::Id constsCase = editor.MakeId();
|
||||
rdcspv::Id baseCase = editor.MakeId();
|
||||
cases.add(rdcspv::OpSelectionMerge(mergeLabel, rdcspv::SelectionControl::None));
|
||||
cases.add(rdcspv::OpBranchConditional(useGatherOffsets, constsCase, baseCase));
|
||||
cases.add(rdcspv::OpBranchConditional(useGradOrGatherOffsets, constsCase, baseCase));
|
||||
|
||||
rdcspv::Id baseResult;
|
||||
{
|
||||
cases.add(rdcspv::OpLabel(baseCase));
|
||||
rdcspv::ImageOperandsAndParamDatas operands = imageOperands;
|
||||
imageOperands.setConstOffset(offsets[i]);
|
||||
|
||||
if(m_pDriver->GetDeviceFeatures().shaderImageGatherExtended)
|
||||
imageOperands.setOffset(offsets[i]);
|
||||
|
||||
rdcspv::Id combined = cases.add(rdcspv::OpSampledImage(
|
||||
texSampCombinedTypes[i], editor.MakeId(), loadedImage, loadedSampler));
|
||||
|
||||
@@ -1889,7 +2002,13 @@ private:
|
||||
{
|
||||
cases.add(rdcspv::OpLabel(constsCase));
|
||||
rdcspv::ImageOperandsAndParamDatas operands = imageOperands;
|
||||
operands.setConstOffsets(gatherOffsets);
|
||||
|
||||
// if this feature isn't available, this path will never be exercised (since we only
|
||||
// come in here when the actual shader used const offsets) so it's fine to drop it in
|
||||
// that case to ensure the module is still legal.
|
||||
if(m_pDriver->GetDeviceFeatures().shaderImageGatherExtended)
|
||||
operands.setConstOffsets(gatherOffsets);
|
||||
|
||||
rdcspv::Id combined = cases.add(rdcspv::OpSampledImage(
|
||||
texSampCombinedTypes[i], editor.MakeId(), loadedImage, loadedSampler));
|
||||
|
||||
@@ -1909,7 +2028,8 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
imageOperands.setConstOffset(offsets[i]);
|
||||
if(m_pDriver->GetDeviceFeatures().shaderImageGatherExtended)
|
||||
imageOperands.setOffset(offsets[i]);
|
||||
|
||||
rdcspv::Id combined = cases.add(rdcspv::OpSampledImage(
|
||||
texSampCombinedTypes[i], editor.MakeId(), loadedImage, loadedSampler));
|
||||
|
||||
Reference in New Issue
Block a user