From be65ec48d768486fc9cb7514891c2243a2839e28 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 16 Jun 2020 19:01:38 +0100 Subject: [PATCH] Process cbuffer/structure types with type annotations --- .../driver/d3d11/d3d11_rendertexture.cpp | 10 +- .../driver/d3d12/d3d12_rendertexture.cpp | 10 +- .../driver/shaders/dxbc/dxbc_bytecode.cpp | 4 +- renderdoc/driver/shaders/dxbc/dxbc_common.h | 2 +- .../driver/shaders/dxbc/dxbc_container.cpp | 75 ++--- .../driver/shaders/dxbc/dxbc_reflect.cpp | 17 +- .../driver/shaders/dxil/dxil_reflect.cpp | 295 +++++++++++++++++- 7 files changed, 330 insertions(+), 83 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_rendertexture.cpp b/renderdoc/driver/d3d11/d3d11_rendertexture.cpp index f331c59d7..445599979 100644 --- a/renderdoc/driver/d3d11/d3d11_rendertexture.cpp +++ b/renderdoc/driver/d3d11/d3d11_rendertexture.cpp @@ -615,7 +615,7 @@ bool D3D11Replay::RenderTextureInternal(TextureDisplay cfg, TexDisplayFlags flag if(var.name == "RENDERDOC_TexDim") { if(var.type.descriptor.rows == 1 && var.type.descriptor.cols == 4 && - var.type.descriptor.type == DXBC::VARTYPE_UINT) + var.type.descriptor.varType == VarType::UInt) { uint32_t *d = (uint32_t *)(byteData + var.offset); @@ -645,7 +645,7 @@ bool D3D11Replay::RenderTextureInternal(TextureDisplay cfg, TexDisplayFlags flag else if(var.name == "RENDERDOC_SelectedMip") { if(var.type.descriptor.rows == 1 && var.type.descriptor.cols == 1 && - var.type.descriptor.type == DXBC::VARTYPE_UINT) + var.type.descriptor.varType == VarType::UInt) { uint32_t *d = (uint32_t *)(byteData + var.offset); @@ -660,7 +660,7 @@ bool D3D11Replay::RenderTextureInternal(TextureDisplay cfg, TexDisplayFlags flag else if(var.name == "RENDERDOC_SelectedSliceFace") { if(var.type.descriptor.rows == 1 && var.type.descriptor.cols == 1 && - var.type.descriptor.type == DXBC::VARTYPE_UINT) + var.type.descriptor.varType == VarType::UInt) { uint32_t *d = (uint32_t *)(byteData + var.offset); @@ -675,7 +675,7 @@ bool D3D11Replay::RenderTextureInternal(TextureDisplay cfg, TexDisplayFlags flag else if(var.name == "RENDERDOC_SelectedSample") { if(var.type.descriptor.rows == 1 && var.type.descriptor.cols == 1 && - var.type.descriptor.type == DXBC::VARTYPE_INT) + var.type.descriptor.varType == VarType::SInt) { int32_t *d = (int32_t *)(byteData + var.offset); @@ -690,7 +690,7 @@ bool D3D11Replay::RenderTextureInternal(TextureDisplay cfg, TexDisplayFlags flag else if(var.name == "RENDERDOC_TextureType") { if(var.type.descriptor.rows == 1 && var.type.descriptor.cols == 1 && - var.type.descriptor.type == DXBC::VARTYPE_UINT) + var.type.descriptor.varType == VarType::UInt) { uint32_t *d = (uint32_t *)(byteData + var.offset); diff --git a/renderdoc/driver/d3d12/d3d12_rendertexture.cpp b/renderdoc/driver/d3d12/d3d12_rendertexture.cpp index eda28d1ed..72f79c10a 100644 --- a/renderdoc/driver/d3d12/d3d12_rendertexture.cpp +++ b/renderdoc/driver/d3d12/d3d12_rendertexture.cpp @@ -542,7 +542,7 @@ bool D3D12Replay::RenderTextureInternal(D3D12_CPU_DESCRIPTOR_HANDLE rtv, Texture if(var.name == "RENDERDOC_TexDim") { if(var.type.descriptor.rows == 1 && var.type.descriptor.cols == 4 && - var.type.descriptor.type == DXBC::VARTYPE_UINT) + var.type.descriptor.varType == VarType::UInt) { uint32_t *d = (uint32_t *)(byteData + var.offset); @@ -576,7 +576,7 @@ bool D3D12Replay::RenderTextureInternal(D3D12_CPU_DESCRIPTOR_HANDLE rtv, Texture else if(var.name == "RENDERDOC_SelectedMip") { if(var.type.descriptor.rows == 1 && var.type.descriptor.cols == 1 && - var.type.descriptor.type == DXBC::VARTYPE_UINT) + var.type.descriptor.varType == VarType::UInt) { uint32_t *d = (uint32_t *)(byteData + var.offset); @@ -591,7 +591,7 @@ bool D3D12Replay::RenderTextureInternal(D3D12_CPU_DESCRIPTOR_HANDLE rtv, Texture else if(var.name == "RENDERDOC_SelectedSliceFace") { if(var.type.descriptor.rows == 1 && var.type.descriptor.cols == 1 && - var.type.descriptor.type == DXBC::VARTYPE_UINT) + var.type.descriptor.varType == VarType::UInt) { uint32_t *d = (uint32_t *)(byteData + var.offset); @@ -606,7 +606,7 @@ bool D3D12Replay::RenderTextureInternal(D3D12_CPU_DESCRIPTOR_HANDLE rtv, Texture else if(var.name == "RENDERDOC_SelectedSample") { if(var.type.descriptor.rows == 1 && var.type.descriptor.cols == 1 && - var.type.descriptor.type == DXBC::VARTYPE_INT) + var.type.descriptor.varType == VarType::SInt) { int32_t *d = (int32_t *)(byteData + var.offset); @@ -621,7 +621,7 @@ bool D3D12Replay::RenderTextureInternal(D3D12_CPU_DESCRIPTOR_HANDLE rtv, Texture else if(var.name == "RENDERDOC_TextureType") { if(var.type.descriptor.rows == 1 && var.type.descriptor.cols == 1 && - var.type.descriptor.type == DXBC::VARTYPE_UINT) + var.type.descriptor.varType == VarType::UInt) { uint32_t *d = (uint32_t *)(byteData + var.offset); diff --git a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp index bca46c12c..3a166f227 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp @@ -358,7 +358,7 @@ DXBC::Reflection *Program::GuessReflection() var.name = cb.name; var.offset = 0; var.type.descriptor.varClass = DXBC::VariableClass::CLASS_STRUCT; - var.type.descriptor.type = DXBC::VariableType::VARTYPE_VOID; + var.type.descriptor.varType = VarType::Unknown; var.type.descriptor.rows = 1; var.type.descriptor.cols = 4; var.type.descriptor.elements = 1; @@ -382,7 +382,7 @@ DXBC::Reflection *Program::GuessReflection() var.type.descriptor.rows = 1; var.type.descriptor.cols = 4; var.type.descriptor.elements = 0; - var.type.descriptor.type = DXBC::VARTYPE_FLOAT; + var.type.descriptor.varType = VarType::Float; var.type.descriptor.varClass = DXBC::CLASS_VECTOR; var.type.descriptor.name = TypeName(var.type.descriptor); diff --git a/renderdoc/driver/shaders/dxbc/dxbc_common.h b/renderdoc/driver/shaders/dxbc/dxbc_common.h index 7ad913356..bb46588ee 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_common.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_common.h @@ -279,7 +279,7 @@ struct CBufferVariableType struct Descriptor { VariableClass varClass; - VariableType type; + VarType varType; uint32_t rows; uint32_t cols; uint32_t elements; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp index 78d2d6611..3356b6a8c 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp @@ -265,32 +265,6 @@ static const uint32_t FOURCC_HASH = MAKE_FOURCC('H', 'A', 'S', 'H'); static const uint32_t FOURCC_SFI0 = MAKE_FOURCC('S', 'F', 'I', '0'); static const uint32_t FOURCC_PSV0 = MAKE_FOURCC('P', 'S', 'V', '0'); -int TypeByteSize(VariableType t) -{ - switch(t) - { - case VARTYPE_UINT8: return 1; - case VARTYPE_BOOL: - case VARTYPE_INT: - case VARTYPE_FLOAT: - case VARTYPE_UINT: - return 4; - // we pretend for our purposes that the 'min' formats round up to 4 bytes. For any external - // interfaces they are treated as regular types, only using lower precision internally. - case VARTYPE_MIN8FLOAT: - case VARTYPE_MIN10FLOAT: - case VARTYPE_MIN16FLOAT: - case VARTYPE_MIN12INT: - case VARTYPE_MIN16INT: - case VARTYPE_MIN16UINT: return 4; - case VARTYPE_DOUBLE: - return 8; - // 'virtual' type. Just return 1 - case VARTYPE_INTERFACE_POINTER: return 1; - default: RDCERR("Trying to take size of undefined type %d", t); return 1; - } -} - ShaderBuiltin GetSystemValue(SVSemantic systemValue) { switch(systemValue) @@ -333,22 +307,15 @@ rdcstr TypeName(CBufferVariableType::Descriptor desc) rdcstr ret; char *type = ""; - switch(desc.type) + switch(desc.varType) { - case VARTYPE_BOOL: type = "bool"; break; - case VARTYPE_INT: type = "int"; break; - case VARTYPE_FLOAT: type = "float"; break; - case VARTYPE_DOUBLE: type = "double"; break; - case VARTYPE_UINT: type = "uint"; break; - case VARTYPE_UINT8: type = "ubyte"; break; - case VARTYPE_VOID: type = "void"; break; - case VARTYPE_INTERFACE_POINTER: type = "interface"; break; - case VARTYPE_MIN8FLOAT: type = "min8float"; break; - case VARTYPE_MIN10FLOAT: type = "min10float"; break; - case VARTYPE_MIN16FLOAT: type = "min16float"; break; - case VARTYPE_MIN12INT: type = "min12int"; break; - case VARTYPE_MIN16INT: type = "min16int"; break; - case VARTYPE_MIN16UINT: type = "min16uint"; break; + case VarType::Bool: type = "bool"; break; + case VarType::SInt: type = "int"; break; + case VarType::Float: type = "float"; break; + case VarType::Double: type = "double"; break; + case VarType::UInt: type = "uint"; break; + case VarType::UByte: type = "ubyte"; break; + case VarType::Unknown: type = "void"; break; default: RDCERR("Unexpected type in RDEF variable type %d", type); } @@ -398,7 +365,23 @@ CBufferVariableType DXBCContainer::ParseRDEFType(const RDEFHeader *h, const byte ret.descriptor.cols = type->cols; ret.descriptor.elements = type->numElems; ret.descriptor.rows = type->rows; - ret.descriptor.type = (VariableType)type->varType; + + switch((VariableType)type->varType) + { + // DXBC treats all cbuffer variables as 32-bit regardless of declaration + case DXBC::VARTYPE_MIN12INT: + case DXBC::VARTYPE_MIN16INT: + case DXBC::VARTYPE_INT: ret.descriptor.varType = VarType::SInt; break; + case DXBC::VARTYPE_BOOL: ret.descriptor.varType = VarType::Bool; break; + case DXBC::VARTYPE_MIN16UINT: + case DXBC::VARTYPE_UINT: ret.descriptor.varType = VarType::UInt; break; + case DXBC::VARTYPE_DOUBLE: ret.descriptor.varType = VarType::Double; break; + case DXBC::VARTYPE_FLOAT: + case DXBC::VARTYPE_MIN8FLOAT: + case DXBC::VARTYPE_MIN10FLOAT: + case DXBC::VARTYPE_MIN16FLOAT: + default: ret.descriptor.varType = VarType::Float; break; + } ret.descriptor.name = TypeName(ret.descriptor); @@ -457,12 +440,12 @@ CBufferVariableType DXBCContainer::ParseRDEFType(const RDEFHeader *h, const byte // the other dimension if(ret.descriptor.varClass == CLASS_MATRIX_COLUMNS) { - ret.descriptor.bytesize = TypeByteSize(ret.descriptor.type) * ret.descriptor.cols * 4 * + ret.descriptor.bytesize = VarTypeByteSize(ret.descriptor.varType) * ret.descriptor.cols * 4 * RDCMAX(1U, ret.descriptor.elements); } else if(ret.descriptor.varClass == CLASS_MATRIX_ROWS) { - ret.descriptor.bytesize = TypeByteSize(ret.descriptor.type) * ret.descriptor.rows * 4 * + ret.descriptor.bytesize = VarTypeByteSize(ret.descriptor.varType) * ret.descriptor.rows * 4 * RDCMAX(1U, ret.descriptor.elements); } else @@ -470,10 +453,10 @@ CBufferVariableType DXBCContainer::ParseRDEFType(const RDEFHeader *h, const byte // arrays also take up a full vector for each element if(ret.descriptor.elements > 1) ret.descriptor.bytesize = - TypeByteSize(ret.descriptor.type) * 4 * RDCMAX(1U, ret.descriptor.elements); + VarTypeByteSize(ret.descriptor.varType) * 4 * RDCMAX(1U, ret.descriptor.elements); else ret.descriptor.bytesize = - TypeByteSize(ret.descriptor.type) * ret.descriptor.rows * ret.descriptor.cols; + VarTypeByteSize(ret.descriptor.varType) * ret.descriptor.rows * ret.descriptor.cols; } } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp b/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp index 26bfc9762..1be53e6a2 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp @@ -33,22 +33,7 @@ static ShaderVariableType MakeShaderVariableType(DXBC::CBufferVariableType type) { ShaderVariableType ret; - switch(type.descriptor.type) - { - // D3D treats all cbuffer variables as 32-bit regardless of declaration - case DXBC::VARTYPE_MIN12INT: - case DXBC::VARTYPE_MIN16INT: - case DXBC::VARTYPE_INT: ret.descriptor.type = VarType::SInt; break; - case DXBC::VARTYPE_BOOL: ret.descriptor.type = VarType::Bool; break; - case DXBC::VARTYPE_MIN16UINT: - case DXBC::VARTYPE_UINT: ret.descriptor.type = VarType::UInt; break; - case DXBC::VARTYPE_DOUBLE: ret.descriptor.type = VarType::Double; break; - case DXBC::VARTYPE_FLOAT: - case DXBC::VARTYPE_MIN8FLOAT: - case DXBC::VARTYPE_MIN10FLOAT: - case DXBC::VARTYPE_MIN16FLOAT: - default: ret.descriptor.type = VarType::Float; break; - } + ret.descriptor.type = type.descriptor.varType; ret.descriptor.rows = (uint8_t)type.descriptor.rows; ret.descriptor.columns = (uint8_t)type.descriptor.cols; ret.descriptor.elements = type.descriptor.elements; diff --git a/renderdoc/driver/shaders/dxil/dxil_reflect.cpp b/renderdoc/driver/shaders/dxil/dxil_reflect.cpp index f9a8e0ae8..80858b8a3 100644 --- a/renderdoc/driver/shaders/dxil/dxil_reflect.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_reflect.cpp @@ -118,6 +118,18 @@ enum class SRVUAVTag StructStride = 1, }; +enum class StructMemberAnnotation +{ + SNorm = 0, + UNorm = 1, + Matrix = 2, + CBufferOffset = 3, + SemanticString = 4, + InterpolationMode = 5, + FieldName = 6, + CompType = 7, +}; + template T getival(const Metadata *m) { @@ -283,7 +295,261 @@ struct DXMeta } }; -static DXBC::ShaderInputBind MakeResourceBind(const Metadata *r, const bool srv) +struct TypeInfo +{ + struct MemberData + { + enum Flags : uint8_t + { + None = 0, + UNorm = 0x1, + SNorm = 0x2, + RowMajor = 0x4, + Matrix = 0x8, + } flags = None; + uint8_t rows = 0, cols = 0; + uint32_t offset; + rdcstr name; + ComponentType type; + }; + + struct StructData + { + uint32_t byteSize; + rdcarray members; + }; + + std::map structData; + + TypeInfo(const Metadata *typeAnnotations) + { + RDCASSERT(typeAnnotations->children.size() >= 2, typeAnnotations->children.size()); + const Metadata *structAnnotations = typeAnnotations->children[0]; + + RDCASSERTEQUAL(getival(structAnnotations->children[0]), 0); + + for(size_t c = 1; c < structAnnotations->children.size(); c += 2) + { + const Type *type = structAnnotations->children[c]->type; + const Metadata *structMembers = structAnnotations->children[c + 1]; + + RDCASSERT(structMembers->children.size() - 1 >= type->members.size(), + structMembers->children.size(), type->members.size()); + + StructData &data = structData[type]; + data.byteSize = getival(structMembers->children[0]); + data.members.resize(type->members.size()); + + for(size_t m = 0; m < type->members.size(); m++) + { + const Metadata *memberIn = structMembers->children[m + 1]; + MemberData &memberOut = data.members[m]; + + for(size_t tag = 0; tag < memberIn->children.size(); tag += 2) + { + StructMemberAnnotation fieldTag = getival(memberIn->children[tag]); + switch(fieldTag) + { + case StructMemberAnnotation::SNorm: + { + if(getival(memberIn->children[tag + 1]) != 0) + memberOut.flags = MemberData::Flags(memberOut.flags | MemberData::SNorm); + break; + } + case StructMemberAnnotation::UNorm: + { + if(getival(memberIn->children[tag + 1]) != 0) + memberOut.flags = MemberData::Flags(memberOut.flags | MemberData::UNorm); + break; + } + case StructMemberAnnotation::Matrix: + { + const Metadata *matrixData = memberIn->children[tag + 1]; + memberOut.rows = getival(matrixData->children[0]); + memberOut.cols = getival(matrixData->children[1]); + bool rowmajor = (getival(matrixData->children[2]) == 1); + if(rowmajor) + memberOut.flags = + MemberData::Flags(memberOut.flags | MemberData::RowMajor | MemberData::Matrix); + else + memberOut.flags = MemberData::Flags(memberOut.flags | MemberData::Matrix); + break; + } + case StructMemberAnnotation::CBufferOffset: + memberOut.offset = getival(memberIn->children[tag + 1]); + break; + case StructMemberAnnotation::SemanticString: break; + case StructMemberAnnotation::InterpolationMode: break; + case StructMemberAnnotation::FieldName: + memberOut.name = memberIn->children[tag + 1]->str; + break; + case StructMemberAnnotation::CompType: + memberOut.type = getival(memberIn->children[tag + 1]); + break; + default: RDCWARN("Unexpected field tag %u", fieldTag); break; + } + } + } + } + } +}; + +static DXBC::CBufferVariableType MakeCBufferVariableType(const TypeInfo &typeInfo, const Type *t) +{ + using namespace DXBC; + + CBufferVariableType ret = {}; + + if(t->type == Type::Scalar || t->type == Type::Vector) + { + ret.descriptor.rows = ret.descriptor.cols = 1; + if(t->type == Type::Vector) + ret.descriptor.cols = t->elemCount; + ret.descriptor.bytesize = (t->bitWidth / 8) * ret.descriptor.cols; + ret.descriptor.varClass = CLASS_SCALAR; + + if(t->scalarType == Type::Float) + { + if(t->bitWidth > 32) + ret.descriptor.varType = VarType::Double; + else if(t->bitWidth == 16) + ret.descriptor.varType = VarType::Half; + else + ret.descriptor.varType = VarType::Float; + } + else + { + // can't distinguish int/uint here, default to signed + if(t->bitWidth > 32) + ret.descriptor.varType = VarType::SLong; + else if(t->bitWidth == 32) + ret.descriptor.varType = VarType::SInt; + else if(t->bitWidth == 16) + ret.descriptor.varType = VarType::SShort; + else if(t->bitWidth == 8) + ret.descriptor.varType = VarType::SByte; + else if(t->bitWidth == 1) + ret.descriptor.varType = VarType::Bool; + } + return ret; + } + else if(t->type == Type::Array) + { + ret = MakeCBufferVariableType(typeInfo, t->inner); + ret.descriptor.elements = t->elemCount; + // assume normal D3D array packing with each element on float4 boundary + ret.descriptor.bytesize += (t->elemCount - 1) * 16; + return ret; + } + else if(t->type == Type::Struct) + { + // processing below + } + else + { + RDCERR("Unexpected type %u iterating cbuffer variable type %s", t->type, t->name.c_str()); + return ret; + } + + // if there are no members, return straight away + if(t->members.empty()) + return ret; + + auto it = typeInfo.structData.find(t); + + if(it != typeInfo.structData.end()) + { + ret.descriptor.bytesize = it->second.byteSize; + ret.descriptor.name = t->name; + if(ret.descriptor.name.beginsWith("struct.")) + ret.descriptor.name.erase(0, 7); + if(ret.descriptor.name.beginsWith("class.")) + ret.descriptor.name.erase(0, 6); + ret.descriptor.varType = VarType::Unknown; + ret.descriptor.varClass = CLASS_STRUCT; + } + else + { + RDCERR("Don't have struct type annotations for %s", t->name.c_str()); + } + + for(size_t i = 0; i < t->members.size(); i++) + { + CBufferVariable var; + var.type = MakeCBufferVariableType(typeInfo, t->members[i]); + if(it != typeInfo.structData.end()) + { + var.name = it->second.members[i].name; + var.offset = it->second.members[i].offset; + + if(it->second.members[i].flags & TypeInfo::MemberData::Matrix) + { + var.type.descriptor.rows = it->second.members[i].rows; + var.type.descriptor.cols = it->second.members[i].cols; + var.type.descriptor.varClass = (it->second.members[i].flags & TypeInfo::MemberData::RowMajor) + ? CLASS_MATRIX_ROWS + : CLASS_MATRIX_COLUMNS; + } + + if(var.type.members.empty() && t->members[i]->type != Type::Struct) + { + switch(it->second.members[i].type) + { + case ComponentType::Invalid: + var.type.descriptor.varType = VarType::Unknown; + RDCERR("Unexpected type in cbuffer annotations"); + break; + case ComponentType::I1: var.type.descriptor.varType = VarType::Bool; break; + case ComponentType::I16: var.type.descriptor.varType = VarType::SShort; break; + case ComponentType::U16: var.type.descriptor.varType = VarType::UShort; break; + case ComponentType::I32: var.type.descriptor.varType = VarType::SInt; break; + case ComponentType::U32: var.type.descriptor.varType = VarType::UInt; break; + case ComponentType::I64: var.type.descriptor.varType = VarType::SLong; break; + case ComponentType::U64: var.type.descriptor.varType = VarType::ULong; break; + case ComponentType::F16: var.type.descriptor.varType = VarType::Half; break; + case ComponentType::F32: var.type.descriptor.varType = VarType::Float; break; + case ComponentType::F64: var.type.descriptor.varType = VarType::Double; break; + case ComponentType::SNormF16: + var.type.descriptor.varType = VarType::Half; + RDCERR("Unexpected type in cbuffer annotations"); + break; + case ComponentType::UNormF16: + var.type.descriptor.varType = VarType::Half; + RDCERR("Unexpected type in cbuffer annotations"); + break; + case ComponentType::SNormF32: + var.type.descriptor.varType = VarType::Float; + RDCERR("Unexpected type in cbuffer annotations"); + break; + case ComponentType::UNormF32: + var.type.descriptor.varType = VarType::Float; + RDCERR("Unexpected type in cbuffer annotations"); + break; + case ComponentType::SNormF64: + var.type.descriptor.varType = VarType::Double; + RDCERR("Unexpected type in cbuffer annotations"); + break; + case ComponentType::UNormF64: + var.type.descriptor.varType = VarType::Double; + RDCERR("Unexpected type in cbuffer annotations"); + break; + } + } + } + else + { + // TODO if we have to handle this case, we should try to calculate the offset + var.name = StringFormat::Fmt("_child%zu", i); + var.offset = 0; + } + ret.members.push_back(var); + } + + return ret; +} + +static void AddResourceBind(DXBC::Reflection *refl, const TypeInfo &typeInfo, const Metadata *r, + const bool srv) { using namespace DXBC; @@ -300,6 +566,7 @@ static DXBC::ShaderInputBind MakeResourceBind(const Metadata *r, const bool srv) bind.numComps = 1; const Type *resType = r->children[(size_t)ResField::VarDecl]->type; + const Type *baseType = resType; // variable should be a pointer to the underlying type RDCASSERT(resType->type == Type::Pointer); @@ -441,7 +708,18 @@ static DXBC::ShaderInputBind MakeResourceBind(const Metadata *r, const bool srv) bind.type = ShaderInputBind::TYPE_UAV_RWSTRUCTURED_WITH_COUNTER; } - return bind; + switch(shape) + { + case ResShape::StructuredBuffer: + case ResShape::StructuredBufferWithCounter: + refl->ResourceBinds[bind.name] = MakeCBufferVariableType(typeInfo, baseType->inner); + default: break; + } + + if(srv) + refl->SRVs.push_back(bind); + else + refl->UAVs.push_back(bind); } DXBC::Reflection *Program::GetReflection() @@ -452,6 +730,8 @@ DXBC::Reflection *Program::GetReflection() DXMeta dx(m_NamedMeta); + TypeInfo typeInfo(dx.typeAnnotations); + if(dx.resources) { RDCASSERTEQUAL(dx.resources->children.size(), 1); @@ -464,7 +744,7 @@ DXBC::Reflection *Program::GetReflection() { for(const Metadata *r : SRVs->children) { - refl->SRVs.push_back(MakeResourceBind(r, true)); + AddResourceBind(refl, typeInfo, r, true); } } @@ -473,7 +753,7 @@ DXBC::Reflection *Program::GetReflection() { for(const Metadata *r : UAVs->children) { - refl->UAVs.push_back(MakeResourceBind(r, false)); + AddResourceBind(refl, typeInfo, r, false); } } @@ -498,10 +778,9 @@ DXBC::Reflection *Program::GetReflection() RDCASSERT(cbufType->type == Type::Pointer); cbufType = cbufType->inner; - for(const Type *member : cbufType->members) - { - (void)member; - } + CBufferVariableType rootType = MakeCBufferVariableType(typeInfo, cbufType); + + bind.variables.swap(rootType.members); refl->CBuffers.push_back(bind); }