diff --git a/renderdoc/driver/shaders/dxbc/dxbc_common.h b/renderdoc/driver/shaders/dxbc/dxbc_common.h index 494499150..669b64fd6 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_common.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_common.h @@ -365,6 +365,8 @@ struct Reflection CBuffer Interfaces; + CBufferVariableType TaskPayload; + std::map ResourceBinds; rdcarray InputSig; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp index 1f95edaae..3242672fc 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp @@ -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++) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp b/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp index 99b0ac911..d457e8867 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp @@ -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])); + } } diff --git a/renderdoc/driver/shaders/dxil/dxil_common.h b/renderdoc/driver/shaders/dxil/dxil_common.h index 438947c3b..f2f24f24d 100644 --- a/renderdoc/driver/shaders/dxil/dxil_common.h +++ b/renderdoc/driver/shaders/dxil/dxil_common.h @@ -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 diff --git a/renderdoc/driver/shaders/dxil/dxil_reflect.cpp b/renderdoc/driver/shaders/dxil/dxil_reflect.cpp index 738401122..f3740f6d2 100644 --- a/renderdoc/driver/shaders/dxil/dxil_reflect.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_reflect.cpp @@ -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(tags.children[t]) == ShaderEntryTag::Compute) - { - Metadata &threadDim = *tags.children[t + 1]; - RDCASSERTEQUAL(threadDim.children.size(), 3); - reflection->DispatchThreadsDimension[0] = getival(threadDim.children[0]); - reflection->DispatchThreadsDimension[1] = getival(threadDim.children[1]); - reflection->DispatchThreadsDimension[2] = getival(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(tags.children[t]) == ShaderEntryTag::Geometry) - { - Metadata &geomData = *tags.children[t + 1]; - RDCASSERTEQUAL(geomData.children.size(), 5); - return getival(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(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(tags.children[t]); + if(shaderTypeTag == ShaderEntryTag::Compute) + { + Metadata &threadDim = *tags.children[t + 1]; + RDCASSERTEQUAL(threadDim.children.size(), 3); + reflection->DispatchThreadsDimension[0] = getival(threadDim.children[0]); + reflection->DispatchThreadsDimension[1] = getival(threadDim.children[1]); + reflection->DispatchThreadsDimension[2] = getival(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(threadDim.children[0]); + reflection->DispatchThreadsDimension[1] = getival(threadDim.children[1]); + reflection->DispatchThreadsDimension[2] = getival(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(threadDim.children[0]); + reflection->DispatchThreadsDimension[1] = getival(threadDim.children[1]); + reflection->DispatchThreadsDimension[2] = getival(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(tags.children[t]) == ShaderEntryTag::Geometry) + { + Metadata &geomData = *tags.children[t + 1]; + RDCASSERTEQUAL(geomData.children.size(), 5); + return getival(geomData.children[3]); + } + else if(getival(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(domainData.children[0]) == 1 + ? D3D_PRIMITIVE_TOPOLOGY_LINELIST + : D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + } + else if(getival(tags.children[t]) == ShaderEntryTag::Mesh) + { + Metadata &meshData = *tags.children[t + 1]; + RDCASSERTEQUAL(meshData.children.size(), 5); + // 1 for lines, 2 for tris + return getival(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)