Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
303 changes: 238 additions & 65 deletions qrenderdoc/Windows/ShaderViewer.cpp

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions qrenderdoc/Windows/ShaderViewer.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ private slots:
rdcarray<UsedDescriptor> m_ReadOnlyResources;
rdcarray<UsedDescriptor> m_ReadWriteResources;
rdcarray<UsedDescriptor> m_Samplers;
rdcarray<UsedDescriptor> m_Constants;
QSet<QPair<int, uint32_t>> m_Breakpoints;
bool m_TempBreakpoint = false;

Expand Down
30 changes: 25 additions & 5 deletions renderdoc/driver/gl/gl_shader_refl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2015,24 +2015,44 @@ void MakeShaderReflection(GLenum shadType, GLuint sepProg, ShaderReflection &ref
{
for(int i = 0; i < numUBOs; i++)
{
if(!ubos[i].empty())
int idx = i;
int arrOffs = uboNames[i].indexOf('[');
// Try to match arrays
// TODO JAKE : EXPLAIN THIS WITH A PROPER COMMENT
if(ubos[i].empty() && arrOffs > 0)
{
rdcstr basename = uboNames[i];
basename.erase(arrOffs, basename.size());

for(int j = 0; j < numUBOs; ++j)
{
if(!ubos[j].empty())
{
if(ubos[j][0].name == basename)
{
idx = j;
break;
}
}
}
}
if(!ubos[idx].empty())
{
ConstantBlock cblock;
cblock.name = uboNames[i];
cblock.bufferBacked = true;
cblock.variables = ubos[idx];

GLenum bufSize = eGL_BUFFER_DATA_SIZE;
GL.glGetProgramResourceiv(sepProg, eGL_UNIFORM_BLOCK, i, 1, &bufSize, 1, NULL,
(GLint *)&cblock.byteSize);

sort(ubos[i]);
sort(cblock.variables);

// can't make perfect guesses of struct alignment but assume std140 for ubos
for(ShaderConstant &member : ubos[i])
for(ShaderConstant &member : cblock.variables)
FixupStructOffsetsAndSize(true, member);

std::swap(cblock.variables, ubos[i]);

refl.constantBlocks.push_back(cblock);
}
}
Expand Down
114 changes: 52 additions & 62 deletions renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,10 +381,16 @@ void WrappedOpenGL::ShaderData::ProcessCompilation(WrappedOpenGL &drv, ResourceI
for(size_t i = 0; i < reflection->constantBlocks.size(); i++)
{
rdcstr name = reflection->constantBlocks[i].name;
// Only match on base name remove any array indexes
int arrOffs = name.indexOf('[');
if(arrOffs > 0)
name.erase(arrOffs, name.size());

bool found = false;
for(size_t j = 0; j < spvReflection.constantBlocks.size(); j++)
{
if(name == spvReflection.constantBlocks[j].name)
const rdcstr &matchName = spvReflection.constantBlocks[j].name;
if(name == matchName)
{
convertedPatchData.cblockInterface.resize_for_index(i);
convertedPatchData.cblockInterface[i] = spvPatchData.cblockInterface[j];
Expand All @@ -404,11 +410,17 @@ void WrappedOpenGL::ShaderData::ProcessCompilation(WrappedOpenGL &drv, ResourceI
const rdcspv::DataType &outerType =
spirv.GetDataType(spirv.GetIDType(spvPatchData.cblockInterface[j]));

rdcstr typeName = outerType.name;
rdcstr matchName = outerType.name;
if(outerType.type == rdcspv::DataType::PointerType)
typeName = spirv.GetDataType(outerType.InnerType()).name;
{
const rdcspv::DataType &innerType = spirv.GetDataType(outerType.InnerType());
if(innerType.type == rdcspv::DataType::ArrayType)
matchName = spirv.GetDataType(innerType.InnerType()).name;
else
matchName = innerType.name;
}

if(name == typeName)
if(name == matchName)
{
convertedPatchData.cblockInterface.resize_for_index(i);
convertedPatchData.cblockInterface[i] = spvPatchData.cblockInterface[j];
Expand All @@ -426,7 +438,8 @@ void WrappedOpenGL::ShaderData::ProcessCompilation(WrappedOpenGL &drv, ResourceI
name += "_var";
for(size_t j = 0; j < spvReflection.constantBlocks.size(); j++)
{
if(name == spvReflection.constantBlocks[j].name)
const rdcstr &matchName = spvReflection.constantBlocks[j].name;
if(name == matchName)
{
convertedPatchData.cblockInterface.resize_for_index(i);
convertedPatchData.cblockInterface[i] = spvPatchData.cblockInterface[j];
Expand Down Expand Up @@ -456,32 +469,22 @@ void WrappedOpenGL::ShaderData::ProcessCompilation(WrappedOpenGL &drv, ResourceI

for(size_t i = 0; i < reflection->readOnlyResources.size(); i++)
{
rdcstr name = reflection->readOnlyResources[i].name;
// Only match on base name remove any array indexes
int arrOffs = name.indexOf('[');
if(arrOffs > 0)
name.erase(arrOffs, name.size());

bool found = false;
for(size_t j = 0; j < spvReflection.readOnlyResources.size(); j++)
{
if(reflection->readOnlyResources[i].name == spvReflection.readOnlyResources[j].name)
{
found = true;
}
else if((spvReflection.readOnlyResources[j].bindArraySize > 1))
{
rdcstr &baseName = spvReflection.readOnlyResources[j].name;
for(uint32_t idx = 0; idx < spvReflection.readOnlyResources[j].bindArraySize; idx++)
{
rdcstr resName = StringFormat::Fmt("%s[%u]", baseName.c_str(), idx);
if(reflection->readOnlyResources[i].name == resName)
{
found = true;
break;
}
}
}
if(found)
if(name == spvReflection.readOnlyResources[j].name)
{
convertedPatchData.roInterface.resize_for_index(i);
convertedPatchData.roInterface[i] = spvPatchData.roInterface[j];
convertedRefl.readOnlyResources.resize_for_index(i);
convertedRefl.readOnlyResources[i] = spvReflection.readOnlyResources[j];
found = true;
break;
}
}
Expand All @@ -500,32 +503,22 @@ void WrappedOpenGL::ShaderData::ProcessCompilation(WrappedOpenGL &drv, ResourceI
for(size_t i = 0; i < reflection->readWriteResources.size(); i++)
{
rdcstr name = reflection->readWriteResources[i].name;
// Only match on base name remove any array indexes
int arrOffs = name.indexOf('[');
if(arrOffs > 0)
name.erase(arrOffs, name.size());

bool found = false;
for(size_t j = 0; j < spvReflection.readWriteResources.size(); j++)
{
if(reflection->readWriteResources[i].name == spvReflection.readWriteResources[j].name)
{
found = true;
}
else if((spvReflection.readWriteResources[j].bindArraySize > 1))
{
rdcstr &baseName = spvReflection.readWriteResources[j].name;
for(uint32_t idx = 0; idx < spvReflection.readWriteResources[j].bindArraySize; idx++)
{
rdcstr resName = StringFormat::Fmt("%s[%u]", baseName.c_str(), idx);
if(reflection->readWriteResources[i].name == resName)
{
found = true;
break;
}
}
}
if(found)
const rdcstr &matchName = spvReflection.readWriteResources[j].name;
if(name == matchName)
{
convertedPatchData.rwInterface.resize_for_index(i);
convertedPatchData.rwInterface[i] = spvPatchData.rwInterface[j];
convertedRefl.readWriteResources.resize_for_index(i);
convertedRefl.readWriteResources[i] = spvReflection.readWriteResources[j];
found = true;
break;
}
}
Expand All @@ -539,11 +532,17 @@ void WrappedOpenGL::ShaderData::ProcessCompilation(WrappedOpenGL &drv, ResourceI
const rdcspv::DataType &outerType =
spirv.GetDataType(spirv.GetIDType(spvPatchData.rwInterface[j]));

rdcstr typeName = outerType.name;
rdcstr matchName = outerType.name;
if(outerType.type == rdcspv::DataType::PointerType)
typeName = spirv.GetDataType(outerType.InnerType()).name;
{
const rdcspv::DataType &innerType = spirv.GetDataType(outerType.InnerType());
if(innerType.type == rdcspv::DataType::ArrayType)
matchName = spirv.GetDataType(innerType.InnerType()).name;
else
matchName = innerType.name;
}

if(name == typeName)
if(name == matchName)
{
convertedPatchData.rwInterface.resize_for_index(i);
convertedPatchData.rwInterface[i] = spvPatchData.rwInterface[j];
Expand All @@ -561,7 +560,8 @@ void WrappedOpenGL::ShaderData::ProcessCompilation(WrappedOpenGL &drv, ResourceI
name += "_var";
for(size_t j = 0; j < spvReflection.readWriteResources.size(); j++)
{
if(name == spvReflection.readWriteResources[j].name)
const rdcstr &matchName = spvReflection.readWriteResources[j].name;
if(name == matchName)
{
convertedPatchData.rwInterface.resize_for_index(i);
convertedPatchData.rwInterface[i] = spvPatchData.rwInterface[j];
Expand All @@ -586,32 +586,22 @@ void WrappedOpenGL::ShaderData::ProcessCompilation(WrappedOpenGL &drv, ResourceI

for(size_t i = 0; i < reflection->samplers.size(); i++)
{
rdcstr name = spvReflection.samplers[i].name;
// Only match on base name remove any array indexes
int arrOffs = name.indexOf('[');
if(arrOffs > 0)
name.erase(arrOffs, name.size());

bool found = false;
for(size_t j = 0; j < spvReflection.samplers.size(); j++)
{
if(reflection->samplers[i].name == spvReflection.samplers[j].name)
{
found = true;
}
else if((spvReflection.samplers[j].bindArraySize > 1))
{
rdcstr &baseName = spvReflection.samplers[j].name;
for(uint32_t idx = 0; idx < spvReflection.samplers[j].bindArraySize; idx++)
{
rdcstr resName = StringFormat::Fmt("%s[%u]", baseName.c_str(), idx);
if(reflection->samplers[i].name == resName)
{
found = true;
break;
}
}
}
if(found)
{
convertedPatchData.samplerInterface.resize_for_index(i);
convertedPatchData.samplerInterface[i] = spvPatchData.samplerInterface[j];
convertedRefl.samplers.resize_for_index(i);
convertedRefl.samplers[i] = spvReflection.samplers[j];
found = true;
break;
}
}
Expand Down
4 changes: 4 additions & 0 deletions renderdoc/driver/shaders/dxbc/dxbc_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4008,6 +4008,10 @@ void ThreadState::StepNext(ShaderDebugState *state, DebugAPIWrapper *apiWrapper,
{
samplerMode = decl.samplerMode;
samplerBinding = GetBindingSlotForDeclaration(*program, decl);

// With SM5.1 sampler arrays need to offset the shader register by the array index
if(program->IsShaderModel51())
samplerBinding.shaderRegister = srcOpers[2].value.u32v[1];
}
if(op.operation == OPCODE_LD && decl.declaration == OPCODE_DCL_RESOURCE &&
decl.resource.dim == RESOURCE_DIMENSION_BUFFER &&
Expand Down
70 changes: 41 additions & 29 deletions renderdoc/driver/shaders/dxil/dxil_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2510,32 +2510,35 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
const ResourceReference *resRef = m_Program.GetResourceReference(resultId);
if(resRef)
{
const rdcarray<ShaderVariable> *list = NULL;
// a static known handle which should be in the global resources container
switch(resRef->resourceBase.resClass)
{
case ResourceClass::CBuffer: list = &m_GlobalState.constantBlocks; break;
case ResourceClass::SRV: list = &m_GlobalState.readOnlyResources; break;
case ResourceClass::UAV: list = &m_GlobalState.readWriteResources; break;
case ResourceClass::Sampler: list = &m_GlobalState.samplers; break;
default:
RDCERR("Invalid ResourceClass %u", (uint32_t)resRef->resourceBase.resClass);
break;
};
RDCASSERT(list);

rdcstr resName = Debugger::GetResourceBaseName(&m_Program, resRef->resourceBase);

const rdcarray<ShaderVariable> &resources = *list;
result.name.clear();
size_t constantBlockIndex = ~0U;
for(uint32_t i = 0; i < resources.size(); ++i)
result.name.clear();

// Non-arrayed resource : a static known handle which should be in the global resources container
if(resRef->resourceBase.regCount == 1)
{
if(resources[i].name == resName)
const rdcarray<ShaderVariable> *list = NULL;
switch(resRef->resourceBase.resClass)
{
constantBlockIndex = i;
result = resources[i];
break;
case ResourceClass::CBuffer: list = &m_GlobalState.constantBlocks; break;
case ResourceClass::SRV: list = &m_GlobalState.readOnlyResources; break;
case ResourceClass::UAV: list = &m_GlobalState.readWriteResources; break;
case ResourceClass::Sampler: list = &m_GlobalState.samplers; break;
default:
RDCERR("Invalid ResourceClass %u", (uint32_t)resRef->resourceBase.resClass);
break;
};
RDCASSERT(list);

const rdcarray<ShaderVariable> &resources = *list;
for(uint32_t i = 0; i < resources.size(); ++i)
{
if(resources[i].name == resName)
{
constantBlockIndex = i;
result = resources[i];
break;
}
}
}
if(result.name.isEmpty())
Expand All @@ -2553,11 +2556,23 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
uint32_t arrayIndex = arg.value.u32v[0];
RDCASSERT(arrayIndex >= resRef->resourceBase.regBase);
arrayIndex -= resRef->resourceBase.regBase;
bool isSRV = (resRef->resourceBase.resClass == ResourceClass::SRV);
DescriptorCategory category = isSRV ? DescriptorCategory::ReadOnlyResource
: DescriptorCategory::ReadWriteResource;
DescriptorCategory category = DescriptorCategory::Unknown;
if(resRef->resourceBase.resClass == ResourceClass::SRV)
{
category = DescriptorCategory::ReadOnlyResource;
result.type = VarType::ReadOnlyResource;
}
else if(resRef->resourceBase.resClass == ResourceClass::UAV)
{
category = DescriptorCategory::ReadWriteResource;
result.type = VarType::ReadWriteResource;
}
else if(resRef->resourceBase.resClass == ResourceClass::Sampler)
{
category = DescriptorCategory::Sampler;
result.type = VarType::Sampler;
}
result.SetBindIndex(ShaderBindIndex(category, resRef->resourceIndex, arrayIndex));
result.type = isSRV ? VarType::ReadOnlyResource : VarType::ReadWriteResource;
// Default to unannotated handle
ClearAnnotatedHandle(result);
}
Expand Down Expand Up @@ -9316,9 +9331,6 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, uint32_t eve
for(uint32_t i = 0; i < list.resources.size(); i++)
{
const ShaderResource &res = list.resources[i];
// Ignore arrays the debugger execution will mark specific array elements used
if(res.bindArraySize > 1)
continue;

// Fetch the resource name
BindingSlot slot(res.fixedBindNumber, res.fixedBindSetOrSpace);
Expand Down
Loading