Add DXIL reflection for task/mesh shaders

This commit is contained in:
baldurk
2023-11-16 16:42:55 +00:00
parent 66d0a10142
commit cc80757e4e
5 changed files with 406 additions and 188 deletions
@@ -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++)
+44 -35
View File
@@ -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
+331 -150
View File
@@ -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 &ampData = *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)