mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-08 16:50:44 +00:00
Add DXIL reflection for task/mesh shaders
This commit is contained in:
@@ -365,6 +365,8 @@ struct Reflection
|
||||
|
||||
CBuffer Interfaces;
|
||||
|
||||
CBufferVariableType TaskPayload;
|
||||
|
||||
std::map<rdcstr, CBufferVariableType> ResourceBinds;
|
||||
|
||||
rdcarray<SigParameter> InputSig;
|
||||
|
||||
@@ -1714,7 +1714,7 @@ DXBCContainer::DXBCContainer(const bytebuf &ByteCode, const rdcstr &debugInfoPat
|
||||
|
||||
bool input = false;
|
||||
bool output = false;
|
||||
bool patch = false;
|
||||
bool patchOrPerPrim = false;
|
||||
|
||||
if(*fourcc == FOURCC_ISGN || *fourcc == FOURCC_ISG1)
|
||||
{
|
||||
@@ -1729,10 +1729,15 @@ DXBCContainer::DXBCContainer(const bytebuf &ByteCode, const rdcstr &debugInfoPat
|
||||
if(*fourcc == FOURCC_PCSG || *fourcc == FOURCC_PSG1)
|
||||
{
|
||||
sig = &m_Reflection->PatchConstantSig;
|
||||
patch = true;
|
||||
|
||||
// for mesh shaders put everything in the output signature
|
||||
if(m_Type == DXBC::ShaderType::Mesh)
|
||||
sig = &m_Reflection->OutputSig;
|
||||
|
||||
patchOrPerPrim = true;
|
||||
}
|
||||
|
||||
RDCASSERT(sig && sig->empty());
|
||||
RDCASSERT(sig && (sig->empty() || m_Type == DXBC::ShaderType::Mesh));
|
||||
|
||||
SIGNElement *el0 = (SIGNElement *)(sign + 1);
|
||||
SIGNElement7 *el7 = (SIGNElement7 *)el0;
|
||||
@@ -1791,6 +1796,10 @@ DXBCContainer::DXBCContainer(const bytebuf &ByteCode, const rdcstr &debugInfoPat
|
||||
desc.compCount = (desc.regChannelMask & 0x1 ? 1 : 0) + (desc.regChannelMask & 0x2 ? 1 : 0) +
|
||||
(desc.regChannelMask & 0x4 ? 1 : 0) + (desc.regChannelMask & 0x8 ? 1 : 0);
|
||||
|
||||
// this is the per-primitive signature for mesh shaders
|
||||
if(m_Type == DXBC::ShaderType::Mesh && patchOrPerPrim)
|
||||
desc.perPrimitiveRate = true;
|
||||
|
||||
RDCASSERT(m_Type != DXBC::ShaderType::Max);
|
||||
|
||||
// pixel shader outputs with registers are always targets
|
||||
@@ -1898,9 +1907,22 @@ DXBCContainer::DXBCContainer(const bytebuf &ByteCode, const rdcstr &debugInfoPat
|
||||
}
|
||||
}
|
||||
|
||||
// sort per-primitive outputs to the end
|
||||
if(m_Type == DXBC::ShaderType::Mesh)
|
||||
{
|
||||
std::stable_sort(m_Reflection->OutputSig.begin(), m_Reflection->OutputSig.end(),
|
||||
[](const SigParameter &a, const SigParameter &b) {
|
||||
return a.perPrimitiveRate < b.perPrimitiveRate;
|
||||
});
|
||||
}
|
||||
|
||||
// make sure to fetch the dispatch threads dimension from disassembly
|
||||
if(m_Type == DXBC::ShaderType::Compute && m_DXBCByteCode)
|
||||
m_DXBCByteCode->FetchComputeProperties(m_Reflection);
|
||||
if((m_Type == DXBC::ShaderType::Compute || m_Type == DXBC::ShaderType::Amplification ||
|
||||
m_Type == DXBC::ShaderType::Mesh) &&
|
||||
m_DXILByteCode)
|
||||
m_DXILByteCode->FetchComputeProperties(m_Reflection);
|
||||
|
||||
// initialise debug chunks last
|
||||
for(uint32_t chunkIdx = 0; chunkIdx < header->numChunks; chunkIdx++)
|
||||
|
||||
@@ -352,80 +352,89 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl,
|
||||
}
|
||||
refl->rawBytes = dxbc->GetShaderBlob();
|
||||
|
||||
refl->dispatchThreadsDimension[0] = dxbc->GetReflection()->DispatchThreadsDimension[0];
|
||||
refl->dispatchThreadsDimension[1] = dxbc->GetReflection()->DispatchThreadsDimension[1];
|
||||
refl->dispatchThreadsDimension[2] = dxbc->GetReflection()->DispatchThreadsDimension[2];
|
||||
const DXBC::Reflection *dxbcRefl = dxbc->GetReflection();
|
||||
|
||||
refl->inputSignature = dxbc->GetReflection()->InputSig;
|
||||
refl->outputSignature = dxbc->GetReflection()->OutputSig;
|
||||
refl->dispatchThreadsDimension[0] = dxbcRefl->DispatchThreadsDimension[0];
|
||||
refl->dispatchThreadsDimension[1] = dxbcRefl->DispatchThreadsDimension[1];
|
||||
refl->dispatchThreadsDimension[2] = dxbcRefl->DispatchThreadsDimension[2];
|
||||
|
||||
refl->inputSignature = dxbcRefl->InputSig;
|
||||
refl->outputSignature = dxbcRefl->OutputSig;
|
||||
|
||||
mapping->inputAttributes.resize(D3Dx_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT);
|
||||
for(int s = 0; s < D3Dx_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; s++)
|
||||
mapping->inputAttributes[s] = s;
|
||||
|
||||
mapping->constantBlocks.resize(dxbc->GetReflection()->CBuffers.size());
|
||||
refl->constantBlocks.resize(dxbc->GetReflection()->CBuffers.size());
|
||||
for(size_t i = 0; i < dxbc->GetReflection()->CBuffers.size(); i++)
|
||||
mapping->constantBlocks.resize(dxbcRefl->CBuffers.size());
|
||||
refl->constantBlocks.resize(dxbcRefl->CBuffers.size());
|
||||
for(size_t i = 0; i < dxbcRefl->CBuffers.size(); i++)
|
||||
{
|
||||
ConstantBlock &cb = refl->constantBlocks[i];
|
||||
|
||||
cb.name = dxbc->GetReflection()->CBuffers[i].name;
|
||||
cb.name = dxbcRefl->CBuffers[i].name;
|
||||
cb.bufferBacked = true;
|
||||
cb.byteSize = dxbc->GetReflection()->CBuffers[i].descriptor.byteSize;
|
||||
cb.byteSize = dxbcRefl->CBuffers[i].descriptor.byteSize;
|
||||
cb.bindPoint = (int32_t)i;
|
||||
|
||||
Bindpoint map;
|
||||
map.arraySize = dxbc->GetReflection()->CBuffers[i].bindCount;
|
||||
map.bindset = dxbc->GetReflection()->CBuffers[i].space;
|
||||
map.bind = dxbc->GetReflection()->CBuffers[i].reg;
|
||||
map.arraySize = dxbcRefl->CBuffers[i].bindCount;
|
||||
map.bindset = dxbcRefl->CBuffers[i].space;
|
||||
map.bind = dxbcRefl->CBuffers[i].reg;
|
||||
map.used = true;
|
||||
|
||||
mapping->constantBlocks[i] = map;
|
||||
|
||||
cb.variables.reserve(dxbc->GetReflection()->CBuffers[i].variables.size());
|
||||
for(size_t v = 0; v < dxbc->GetReflection()->CBuffers[i].variables.size(); v++)
|
||||
cb.variables.reserve(dxbcRefl->CBuffers[i].variables.size());
|
||||
for(size_t v = 0; v < dxbcRefl->CBuffers[i].variables.size(); v++)
|
||||
{
|
||||
cb.variables.push_back(
|
||||
MakeConstantBufferVariable(true, dxbc->GetReflection()->CBuffers[i].variables[v]));
|
||||
cb.variables.push_back(MakeConstantBufferVariable(true, dxbcRefl->CBuffers[i].variables[v]));
|
||||
}
|
||||
|
||||
FixupEmptyStructs(cb.variables);
|
||||
}
|
||||
|
||||
mapping->samplers.resize(dxbc->GetReflection()->Samplers.size());
|
||||
refl->samplers.resize(dxbc->GetReflection()->Samplers.size());
|
||||
for(size_t i = 0; i < dxbc->GetReflection()->Samplers.size(); i++)
|
||||
mapping->samplers.resize(dxbcRefl->Samplers.size());
|
||||
refl->samplers.resize(dxbcRefl->Samplers.size());
|
||||
for(size_t i = 0; i < dxbcRefl->Samplers.size(); i++)
|
||||
{
|
||||
ShaderSampler &s = refl->samplers[i];
|
||||
|
||||
s.name = dxbc->GetReflection()->Samplers[i].name;
|
||||
s.name = dxbcRefl->Samplers[i].name;
|
||||
s.bindPoint = (int32_t)i;
|
||||
|
||||
Bindpoint map;
|
||||
map.arraySize = 1;
|
||||
map.bindset = dxbc->GetReflection()->Samplers[i].space;
|
||||
map.bind = dxbc->GetReflection()->Samplers[i].reg;
|
||||
map.bindset = dxbcRefl->Samplers[i].space;
|
||||
map.bind = dxbcRefl->Samplers[i].reg;
|
||||
map.used = true;
|
||||
|
||||
mapping->samplers[i] = map;
|
||||
}
|
||||
|
||||
mapping->readOnlyResources.resize(dxbc->GetReflection()->SRVs.size());
|
||||
refl->readOnlyResources.resize(dxbc->GetReflection()->SRVs.size());
|
||||
MakeResourceList(true, dxbc, dxbc->GetReflection()->SRVs, mapping->readOnlyResources,
|
||||
refl->readOnlyResources);
|
||||
mapping->readOnlyResources.resize(dxbcRefl->SRVs.size());
|
||||
refl->readOnlyResources.resize(dxbcRefl->SRVs.size());
|
||||
MakeResourceList(true, dxbc, dxbcRefl->SRVs, mapping->readOnlyResources, refl->readOnlyResources);
|
||||
|
||||
mapping->readWriteResources.resize(dxbc->GetReflection()->UAVs.size());
|
||||
refl->readWriteResources.resize(dxbc->GetReflection()->UAVs.size());
|
||||
MakeResourceList(false, dxbc, dxbc->GetReflection()->UAVs, mapping->readWriteResources,
|
||||
mapping->readWriteResources.resize(dxbcRefl->UAVs.size());
|
||||
refl->readWriteResources.resize(dxbcRefl->UAVs.size());
|
||||
MakeResourceList(false, dxbc, dxbcRefl->UAVs, mapping->readWriteResources,
|
||||
refl->readWriteResources);
|
||||
|
||||
uint32_t numInterfaces = 0;
|
||||
for(size_t i = 0; i < dxbc->GetReflection()->Interfaces.variables.size(); i++)
|
||||
numInterfaces = RDCMAX(dxbc->GetReflection()->Interfaces.variables[i].offset + 1, numInterfaces);
|
||||
for(size_t i = 0; i < dxbcRefl->Interfaces.variables.size(); i++)
|
||||
numInterfaces = RDCMAX(dxbcRefl->Interfaces.variables[i].offset + 1, numInterfaces);
|
||||
|
||||
refl->interfaces.resize(numInterfaces);
|
||||
for(size_t i = 0; i < dxbc->GetReflection()->Interfaces.variables.size(); i++)
|
||||
refl->interfaces[dxbc->GetReflection()->Interfaces.variables[i].offset] =
|
||||
dxbc->GetReflection()->Interfaces.variables[i].name;
|
||||
for(size_t i = 0; i < dxbcRefl->Interfaces.variables.size(); i++)
|
||||
refl->interfaces[dxbcRefl->Interfaces.variables[i].offset] =
|
||||
dxbcRefl->Interfaces.variables[i].name;
|
||||
|
||||
refl->taskPayload.bufferBacked = false;
|
||||
refl->taskPayload.name = dxbcRefl->TaskPayload.name;
|
||||
refl->taskPayload.variables.reserve(dxbcRefl->TaskPayload.members.size());
|
||||
for(size_t v = 0; v < dxbcRefl->TaskPayload.members.size(); v++)
|
||||
{
|
||||
refl->taskPayload.variables.push_back(
|
||||
MakeConstantBufferVariable(false, dxbcRefl->TaskPayload.members[v]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ enum class ComponentType
|
||||
UNormF64,
|
||||
};
|
||||
|
||||
VarType VarTypeForComponentType(ComponentType compType);
|
||||
|
||||
enum class ResourceKind
|
||||
{
|
||||
Unknown = 0,
|
||||
@@ -88,6 +90,8 @@ enum class ShaderEntryTag
|
||||
Domain = 2,
|
||||
Hull = 3,
|
||||
Compute = 4,
|
||||
Mesh = 9,
|
||||
Amplification = 10,
|
||||
};
|
||||
|
||||
enum class ResField
|
||||
|
||||
@@ -57,124 +57,6 @@ T getival(const Metadata *m)
|
||||
return T();
|
||||
}
|
||||
|
||||
void Program::FetchComputeProperties(DXBC::Reflection *reflection)
|
||||
{
|
||||
for(size_t i = 0; i < m_Functions.size(); i++)
|
||||
{
|
||||
const Function &f = *m_Functions[i];
|
||||
|
||||
if(f.name.beginsWith("dx.op.threadId"))
|
||||
{
|
||||
SigParameter param;
|
||||
param.systemValue = ShaderBuiltin::DispatchThreadIndex;
|
||||
param.compCount = 3;
|
||||
param.regChannelMask = param.channelUsedMask = 0x7;
|
||||
param.semanticIdxName = param.semanticName = "threadId";
|
||||
reflection->InputSig.push_back(param);
|
||||
}
|
||||
else if(f.name.beginsWith("dx.op.groupId"))
|
||||
{
|
||||
SigParameter param;
|
||||
param.systemValue = ShaderBuiltin::GroupIndex;
|
||||
param.compCount = 3;
|
||||
param.regChannelMask = param.channelUsedMask = 0x7;
|
||||
param.semanticIdxName = param.semanticName = "groupID";
|
||||
reflection->InputSig.push_back(param);
|
||||
}
|
||||
else if(f.name.beginsWith("dx.op.threadIdInGroup"))
|
||||
{
|
||||
SigParameter param;
|
||||
param.systemValue = ShaderBuiltin::GroupThreadIndex;
|
||||
param.compCount = 3;
|
||||
param.regChannelMask = param.channelUsedMask = 0x7;
|
||||
param.semanticIdxName = param.semanticName = "threadIdInGroup";
|
||||
reflection->InputSig.push_back(param);
|
||||
}
|
||||
else if(f.name.beginsWith("dx.op.flattenedThreadIdInGroup"))
|
||||
{
|
||||
SigParameter param;
|
||||
param.systemValue = ShaderBuiltin::GroupFlatIndex;
|
||||
param.compCount = 1;
|
||||
param.regChannelMask = param.channelUsedMask = 0x1;
|
||||
param.semanticIdxName = param.semanticName = "flattenedThreadIdInGroup";
|
||||
reflection->InputSig.push_back(param);
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < m_NamedMeta.size(); i++)
|
||||
{
|
||||
const NamedMetadata &m = *m_NamedMeta[i];
|
||||
if(m.name == "dx.entryPoints")
|
||||
{
|
||||
// expect only one child for this, DX doesn't support multiple entry points for compute
|
||||
// shaders
|
||||
RDCASSERTEQUAL(m.children.size(), 1);
|
||||
Metadata &entry = *m.children[0];
|
||||
RDCASSERTEQUAL(entry.children.size(), 5);
|
||||
Metadata &tags = *entry.children[4];
|
||||
|
||||
for(size_t t = 0; t < tags.children.size(); t += 2)
|
||||
{
|
||||
RDCASSERT(tags.children[t]->isConstant);
|
||||
if(getival<ShaderEntryTag>(tags.children[t]) == ShaderEntryTag::Compute)
|
||||
{
|
||||
Metadata &threadDim = *tags.children[t + 1];
|
||||
RDCASSERTEQUAL(threadDim.children.size(), 3);
|
||||
reflection->DispatchThreadsDimension[0] = getival<uint32_t>(threadDim.children[0]);
|
||||
reflection->DispatchThreadsDimension[1] = getival<uint32_t>(threadDim.children[1]);
|
||||
reflection->DispatchThreadsDimension[2] = getival<uint32_t>(threadDim.children[2]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RDCERR("Couldn't find thread dimension tag in shader");
|
||||
|
||||
reflection->DispatchThreadsDimension[0] = 1;
|
||||
reflection->DispatchThreadsDimension[1] = 1;
|
||||
reflection->DispatchThreadsDimension[2] = 1;
|
||||
}
|
||||
|
||||
D3D_PRIMITIVE_TOPOLOGY Program::GetOutputTopology()
|
||||
{
|
||||
if(m_Type != DXBC::ShaderType::Geometry && m_Type != DXBC::ShaderType::Domain)
|
||||
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
|
||||
for(size_t i = 0; i < m_NamedMeta.size(); i++)
|
||||
{
|
||||
const NamedMetadata &m = *m_NamedMeta[i];
|
||||
if(m.name == "dx.entryPoints")
|
||||
{
|
||||
// expect only one child for this, DX doesn't support multiple entry points for compute
|
||||
// shaders
|
||||
RDCASSERTEQUAL(m.children.size(), 1);
|
||||
Metadata &entry = *m.children[0];
|
||||
RDCASSERTEQUAL(entry.children.size(), 5);
|
||||
Metadata &tags = *entry.children[4];
|
||||
|
||||
for(size_t t = 0; t < tags.children.size(); t += 2)
|
||||
{
|
||||
RDCASSERT(tags.children[t]->isConstant);
|
||||
if(getival<ShaderEntryTag>(tags.children[t]) == ShaderEntryTag::Geometry)
|
||||
{
|
||||
Metadata &geomData = *tags.children[t + 1];
|
||||
RDCASSERTEQUAL(geomData.children.size(), 5);
|
||||
return getival<D3D_PRIMITIVE_TOPOLOGY>(geomData.children[3]);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RDCERR("Couldn't find topology tag in shader");
|
||||
|
||||
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
}
|
||||
|
||||
struct DXMeta
|
||||
{
|
||||
struct
|
||||
@@ -348,6 +230,285 @@ struct TypeInfo
|
||||
}
|
||||
};
|
||||
|
||||
static DXBC::CBufferVariableType MakePayloadType(const TypeInfo &typeInfo, const Type *t)
|
||||
{
|
||||
using namespace DXBC;
|
||||
|
||||
CBufferVariableType ret = {};
|
||||
|
||||
ret.elements = 1;
|
||||
|
||||
if(t->type == Type::Scalar || t->type == Type::Vector)
|
||||
{
|
||||
ret.rows = ret.cols = 1;
|
||||
if(t->type == Type::Vector)
|
||||
ret.cols = t->elemCount;
|
||||
ret.bytesize = (t->bitWidth / 8) * ret.cols;
|
||||
ret.varClass = CLASS_SCALAR;
|
||||
|
||||
if(t->scalarType == Type::Float)
|
||||
{
|
||||
if(t->bitWidth > 32)
|
||||
ret.varType = VarType::Double;
|
||||
else if(t->bitWidth == 16)
|
||||
ret.varType = VarType::Half;
|
||||
else
|
||||
ret.varType = VarType::Float;
|
||||
}
|
||||
else
|
||||
{
|
||||
// can't distinguish int/uint here, default to signed
|
||||
if(t->bitWidth > 32)
|
||||
ret.varType = VarType::SLong;
|
||||
else if(t->bitWidth == 32)
|
||||
ret.varType = VarType::SInt;
|
||||
else if(t->bitWidth == 16)
|
||||
ret.varType = VarType::SShort;
|
||||
else if(t->bitWidth == 8)
|
||||
ret.varType = VarType::SByte;
|
||||
else if(t->bitWidth == 1)
|
||||
ret.varType = VarType::Bool;
|
||||
}
|
||||
|
||||
ret.name = ToStr(ret.varType);
|
||||
if(t->type == Type::Vector)
|
||||
ret.name += ToStr(ret.cols);
|
||||
}
|
||||
else if(t->type == Type::Array)
|
||||
{
|
||||
ret = MakePayloadType(typeInfo, t->inner);
|
||||
ret.elements *= RDCMAX(1U, t->elemCount);
|
||||
ret.bytesize += (ret.elements - 1) * ret.bytesize;
|
||||
}
|
||||
else if(t->type == Type::Struct)
|
||||
{
|
||||
ret.name = t->name;
|
||||
ret.varType = VarType::Unknown;
|
||||
ret.varClass = CLASS_STRUCT;
|
||||
|
||||
auto it = typeInfo.structData.find(t);
|
||||
|
||||
char structPrefix[] = "struct.";
|
||||
if(ret.name.beginsWith(structPrefix))
|
||||
ret.name.erase(0, sizeof(structPrefix) - 1);
|
||||
|
||||
char classPrefix[] = "class.";
|
||||
if(ret.name.beginsWith(classPrefix))
|
||||
ret.name.erase(0, sizeof(classPrefix) - 1);
|
||||
|
||||
for(size_t i = 0; i < t->members.size(); i++)
|
||||
{
|
||||
ret.members.push_back({});
|
||||
ret.members.back().type = MakePayloadType(typeInfo, t->members[i]);
|
||||
|
||||
if(it != typeInfo.structData.end())
|
||||
ret.members.back().name = it->second.members[i].name;
|
||||
else
|
||||
ret.members.back().name = StringFormat::Fmt("member%zu", i);
|
||||
|
||||
ret.bytesize += ret.members.back().type.bytesize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected type %u iterating cbuffer variable type %s", t->type, t->name.c_str());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Program::FetchComputeProperties(DXBC::Reflection *reflection)
|
||||
{
|
||||
DXMeta dx(m_NamedMeta);
|
||||
|
||||
TypeInfo typeInfo(dx.typeAnnotations);
|
||||
|
||||
for(size_t i = 0; i < m_Functions.size(); i++)
|
||||
{
|
||||
const Function &f = *m_Functions[i];
|
||||
|
||||
if(f.name.beginsWith("dx.op.threadId"))
|
||||
{
|
||||
SigParameter param;
|
||||
param.systemValue = ShaderBuiltin::DispatchThreadIndex;
|
||||
param.compCount = 3;
|
||||
param.regChannelMask = param.channelUsedMask = 0x7;
|
||||
param.semanticIdxName = param.semanticName = "threadId";
|
||||
reflection->InputSig.push_back(param);
|
||||
}
|
||||
else if(f.name.beginsWith("dx.op.groupId"))
|
||||
{
|
||||
SigParameter param;
|
||||
param.systemValue = ShaderBuiltin::GroupIndex;
|
||||
param.compCount = 3;
|
||||
param.regChannelMask = param.channelUsedMask = 0x7;
|
||||
param.semanticIdxName = param.semanticName = "groupID";
|
||||
reflection->InputSig.push_back(param);
|
||||
}
|
||||
else if(f.name.beginsWith("dx.op.threadIdInGroup"))
|
||||
{
|
||||
SigParameter param;
|
||||
param.systemValue = ShaderBuiltin::GroupThreadIndex;
|
||||
param.compCount = 3;
|
||||
param.regChannelMask = param.channelUsedMask = 0x7;
|
||||
param.semanticIdxName = param.semanticName = "threadIdInGroup";
|
||||
reflection->InputSig.push_back(param);
|
||||
}
|
||||
else if(f.name.beginsWith("dx.op.flattenedThreadIdInGroup"))
|
||||
{
|
||||
SigParameter param;
|
||||
param.systemValue = ShaderBuiltin::GroupFlatIndex;
|
||||
param.compCount = 1;
|
||||
param.regChannelMask = param.channelUsedMask = 0x1;
|
||||
param.semanticIdxName = param.semanticName = "flattenedThreadIdInGroup";
|
||||
reflection->InputSig.push_back(param);
|
||||
}
|
||||
|
||||
if(m_Type == DXBC::ShaderType::Amplification)
|
||||
{
|
||||
for(const Instruction *in : f.instructions)
|
||||
{
|
||||
const Instruction &inst = *in;
|
||||
|
||||
if(inst.op == Operation::Call && inst.getFuncCall()->name.beginsWith("dx.op.dispatchMesh"))
|
||||
{
|
||||
if(inst.args.size() != 5)
|
||||
{
|
||||
RDCERR("Unexpected number of arguments to dispatchMesh");
|
||||
continue;
|
||||
}
|
||||
GlobalVar *payloadVariable = cast<GlobalVar>(inst.args[4]);
|
||||
if(!payloadVariable)
|
||||
{
|
||||
RDCERR("Unexpected non-variable payload argument to dispatchMesh");
|
||||
continue;
|
||||
}
|
||||
|
||||
Type *payloadType = (Type *)payloadVariable->type;
|
||||
|
||||
RDCASSERT(payloadType->type == Type::Pointer);
|
||||
payloadType = (Type *)payloadType->inner;
|
||||
|
||||
reflection->TaskPayload = MakePayloadType(typeInfo, payloadType);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < m_NamedMeta.size(); i++)
|
||||
{
|
||||
const NamedMetadata &m = *m_NamedMeta[i];
|
||||
if(m.name == "dx.entryPoints")
|
||||
{
|
||||
// expect only one child for this, DX doesn't support multiple entry points for compute
|
||||
// shaders
|
||||
RDCASSERTEQUAL(m.children.size(), 1);
|
||||
Metadata &entry = *m.children[0];
|
||||
RDCASSERTEQUAL(entry.children.size(), 5);
|
||||
Metadata &tags = *entry.children[4];
|
||||
|
||||
for(size_t t = 0; t < tags.children.size(); t += 2)
|
||||
{
|
||||
RDCASSERT(tags.children[t]->isConstant);
|
||||
ShaderEntryTag shaderTypeTag = getival<ShaderEntryTag>(tags.children[t]);
|
||||
if(shaderTypeTag == ShaderEntryTag::Compute)
|
||||
{
|
||||
Metadata &threadDim = *tags.children[t + 1];
|
||||
RDCASSERTEQUAL(threadDim.children.size(), 3);
|
||||
reflection->DispatchThreadsDimension[0] = getival<uint32_t>(threadDim.children[0]);
|
||||
reflection->DispatchThreadsDimension[1] = getival<uint32_t>(threadDim.children[1]);
|
||||
reflection->DispatchThreadsDimension[2] = getival<uint32_t>(threadDim.children[2]);
|
||||
return;
|
||||
}
|
||||
else if(shaderTypeTag == ShaderEntryTag::Amplification)
|
||||
{
|
||||
Metadata &Data = *tags.children[t + 1];
|
||||
Metadata &threadDim = *ampData.children[0];
|
||||
RDCASSERTEQUAL(threadDim.children.size(), 3);
|
||||
reflection->DispatchThreadsDimension[0] = getival<uint32_t>(threadDim.children[0]);
|
||||
reflection->DispatchThreadsDimension[1] = getival<uint32_t>(threadDim.children[1]);
|
||||
reflection->DispatchThreadsDimension[2] = getival<uint32_t>(threadDim.children[2]);
|
||||
return;
|
||||
}
|
||||
else if(shaderTypeTag == ShaderEntryTag::Mesh)
|
||||
{
|
||||
Metadata &meshData = *tags.children[t + 1];
|
||||
Metadata &threadDim = *meshData.children[0];
|
||||
RDCASSERTEQUAL(threadDim.children.size(), 3);
|
||||
reflection->DispatchThreadsDimension[0] = getival<uint32_t>(threadDim.children[0]);
|
||||
reflection->DispatchThreadsDimension[1] = getival<uint32_t>(threadDim.children[1]);
|
||||
reflection->DispatchThreadsDimension[2] = getival<uint32_t>(threadDim.children[2]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RDCERR("Couldn't find thread dimension tag in shader");
|
||||
|
||||
reflection->DispatchThreadsDimension[0] = 1;
|
||||
reflection->DispatchThreadsDimension[1] = 1;
|
||||
reflection->DispatchThreadsDimension[2] = 1;
|
||||
}
|
||||
|
||||
D3D_PRIMITIVE_TOPOLOGY Program::GetOutputTopology()
|
||||
{
|
||||
if(m_Type != DXBC::ShaderType::Geometry && m_Type != DXBC::ShaderType::Domain &&
|
||||
m_Type != DXBC::ShaderType::Mesh)
|
||||
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
|
||||
for(size_t i = 0; i < m_NamedMeta.size(); i++)
|
||||
{
|
||||
const NamedMetadata &m = *m_NamedMeta[i];
|
||||
if(m.name == "dx.entryPoints")
|
||||
{
|
||||
// expect only one child for this, DX doesn't support multiple entry points for compute
|
||||
// shaders
|
||||
RDCASSERTEQUAL(m.children.size(), 1);
|
||||
Metadata &entry = *m.children[0];
|
||||
RDCASSERTEQUAL(entry.children.size(), 5);
|
||||
Metadata &tags = *entry.children[4];
|
||||
|
||||
for(size_t t = 0; t < tags.children.size(); t += 2)
|
||||
{
|
||||
RDCASSERT(tags.children[t]->isConstant);
|
||||
if(getival<ShaderEntryTag>(tags.children[t]) == ShaderEntryTag::Geometry)
|
||||
{
|
||||
Metadata &geomData = *tags.children[t + 1];
|
||||
RDCASSERTEQUAL(geomData.children.size(), 5);
|
||||
return getival<D3D_PRIMITIVE_TOPOLOGY>(geomData.children[3]);
|
||||
}
|
||||
else if(getival<ShaderEntryTag>(tags.children[t]) == ShaderEntryTag::Domain)
|
||||
{
|
||||
Metadata &domainData = *tags.children[t + 1];
|
||||
RDCASSERTEQUAL(domainData.children.size(), 2);
|
||||
// 1 for isoline, 2 for tri and 3 for quad (which outputs tris)
|
||||
return getival<uint32_t>(domainData.children[0]) == 1
|
||||
? D3D_PRIMITIVE_TOPOLOGY_LINELIST
|
||||
: D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
}
|
||||
else if(getival<ShaderEntryTag>(tags.children[t]) == ShaderEntryTag::Mesh)
|
||||
{
|
||||
Metadata &meshData = *tags.children[t + 1];
|
||||
RDCASSERTEQUAL(meshData.children.size(), 5);
|
||||
// 1 for lines, 2 for tris
|
||||
return getival<uint32_t>(meshData.children[3]) == 1 ? D3D_PRIMITIVE_TOPOLOGY_LINELIST
|
||||
: D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RDCERR("Couldn't find topology tag in shader");
|
||||
|
||||
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
}
|
||||
|
||||
// a struct is empty if it has no members, or all members are empty structs
|
||||
static bool IsEmptyStruct(const Type *t)
|
||||
{
|
||||
@@ -369,6 +530,54 @@ static bool IsEmptyStruct(const Type *t)
|
||||
return true;
|
||||
}
|
||||
|
||||
VarType VarTypeForComponentType(ComponentType compType)
|
||||
{
|
||||
VarType varType;
|
||||
switch(compType)
|
||||
{
|
||||
default:
|
||||
case ComponentType::Invalid:
|
||||
varType = VarType::Unknown;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::I1: varType = VarType::Bool; break;
|
||||
case ComponentType::I16: varType = VarType::SShort; break;
|
||||
case ComponentType::U16: varType = VarType::UShort; break;
|
||||
case ComponentType::I32: varType = VarType::SInt; break;
|
||||
case ComponentType::U32: varType = VarType::UInt; break;
|
||||
case ComponentType::I64: varType = VarType::SLong; break;
|
||||
case ComponentType::U64: varType = VarType::ULong; break;
|
||||
case ComponentType::F16: varType = VarType::Half; break;
|
||||
case ComponentType::F32: varType = VarType::Float; break;
|
||||
case ComponentType::F64: varType = VarType::Double; break;
|
||||
case ComponentType::SNormF16:
|
||||
varType = VarType::Half;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::UNormF16:
|
||||
varType = VarType::Half;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::SNormF32:
|
||||
varType = VarType::Float;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::UNormF32:
|
||||
varType = VarType::Float;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::SNormF64:
|
||||
varType = VarType::Double;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::UNormF64:
|
||||
varType = VarType::Double;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
}
|
||||
return varType;
|
||||
}
|
||||
|
||||
static DXBC::CBufferVariableType MakeCBufferVariableType(const TypeInfo &typeInfo, const Type *t)
|
||||
{
|
||||
using namespace DXBC;
|
||||
@@ -508,44 +717,16 @@ static DXBC::CBufferVariableType MakeCBufferVariableType(const TypeInfo &typeInf
|
||||
switch(it->second.members[i].type)
|
||||
{
|
||||
case ComponentType::Invalid:
|
||||
var.type.varType = VarType::Unknown;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::I1: var.type.varType = VarType::Bool; break;
|
||||
case ComponentType::I16: var.type.varType = VarType::SShort; break;
|
||||
case ComponentType::U16: var.type.varType = VarType::UShort; break;
|
||||
case ComponentType::I32: var.type.varType = VarType::SInt; break;
|
||||
case ComponentType::U32: var.type.varType = VarType::UInt; break;
|
||||
case ComponentType::I64: var.type.varType = VarType::SLong; break;
|
||||
case ComponentType::U64: var.type.varType = VarType::ULong; break;
|
||||
case ComponentType::F16: var.type.varType = VarType::Half; break;
|
||||
case ComponentType::F32: var.type.varType = VarType::Float; break;
|
||||
case ComponentType::F64: var.type.varType = VarType::Double; break;
|
||||
case ComponentType::SNormF16:
|
||||
var.type.varType = VarType::Half;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::UNormF16:
|
||||
var.type.varType = VarType::Half;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::SNormF32:
|
||||
var.type.varType = VarType::Float;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::UNormF32:
|
||||
var.type.varType = VarType::Float;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::SNormF64:
|
||||
var.type.varType = VarType::Double;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::UNormF64:
|
||||
var.type.varType = VarType::Double;
|
||||
RDCERR("Unexpected type in cbuffer annotations");
|
||||
break;
|
||||
case ComponentType::UNormF64: RDCERR("Unexpected type in cbuffer annotations"); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
var.type.varType = VarTypeForComponentType(it->second.members[i].type);
|
||||
}
|
||||
|
||||
if(it->second.members[i].flags & TypeInfo::MemberData::Matrix)
|
||||
|
||||
Reference in New Issue
Block a user