Detect and prevent crashes on broken dxc-produced task shaders

This commit is contained in:
baldurk
2023-11-06 16:37:58 +00:00
parent 8f945ab404
commit d898e2ac09
3 changed files with 46 additions and 15 deletions
@@ -1393,24 +1393,39 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st
{
if(varType->type != DataType::StructType)
{
// global loose variable - add to $Globals block
RDCASSERT(varType->type == DataType::ScalarType || varType->type == DataType::VectorType ||
varType->type == DataType::MatrixType || varType->type == DataType::ArrayType);
RDCASSERT(sourceAPI == GraphicsAPI::OpenGL);
ShaderConstant constant;
MakeConstantBlockVariable(constant, pointerTypes, effectiveStorage, *varType,
strings[global.id], decorations[global.id], specInfo);
if(isArray)
constant.type.elements = arraySize;
if(taskPayload)
{
if(!patchData.invalidTaskPayload)
{
RDCWARN(
"Unhandled case - non-struct task payload. Most likely DXC bug as only one task "
"payload variable allowed per entry point.");
taskPayloadBlock.name = "invalid";
taskPayloadBlock.bufferBacked = false;
patchData.invalidTaskPayload = true;
}
}
else
constant.type.elements = 0;
{
// global loose variable - add to $Globals block
RDCASSERT(varType->type == DataType::ScalarType || varType->type == DataType::VectorType ||
varType->type == DataType::MatrixType || varType->type == DataType::ArrayType);
RDCASSERT(sourceAPI == GraphicsAPI::OpenGL);
constant.byteOffset = decorations[global.id].location;
ShaderConstant constant;
globalsblock.variables.push_back(constant);
MakeConstantBlockVariable(constant, pointerTypes, effectiveStorage, *varType,
strings[global.id], decorations[global.id], specInfo);
if(isArray)
constant.type.elements = arraySize;
else
constant.type.elements = 0;
constant.byteOffset = decorations[global.id].location;
globalsblock.variables.push_back(constant);
}
}
else if(taskPayload)
{
@@ -72,6 +72,10 @@ struct SPIRVPatchData
// for mesh shaders, the maximum number of vertices/primitives generated by each meshlet
uint32_t maxVertices = 0, maxPrimitives = 0;
// if an invalid task payload is detected (non-struct, due to dxc bug generating many scalars
// instead of one struct)
bool invalidTaskPayload = false;
bool usesPrintf = false;
};
+12
View File
@@ -2848,6 +2848,12 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
ret.taskout = ret.meshout;
}
if(meshShad.patchData->invalidTaskPayload)
{
ret.meshout.status = ret.taskout.status = "Invalid task payload, likely generated by dxc bug";
return;
}
if(meshrefl->outputSignature.empty())
{
ret.meshout.status = "mesh shader has no declared outputs";
@@ -2952,6 +2958,12 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
const VulkanCreationInfo::Pipeline::Shader &taskShad =
pipeInfo.shaders[(size_t)ShaderStage::Task];
if(taskShad.patchData->invalidTaskPayload)
{
ret.meshout.status = ret.taskout.status = "Invalid task payload, likely generated by dxc bug";
return;
}
const VulkanCreationInfo::ShaderModule &taskInfo = creationInfo.m_ShaderModule[taskShad.module];
rdcarray<uint32_t> taskSpirv = taskInfo.spirv.GetSPIRV();