From 9887b09658c210d12efe0984d77adcee9ea99b3f Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 14 Jul 2025 22:36:30 +0200 Subject: [PATCH 001/126] Added rewriter option ConsistentBindings (-consistent-bindings) for the IDxcRewriter, this will allow generating register ids for registers that don't fully define them. --- include/dxc/Support/HLSLOptions.h | 1 + include/dxc/Support/HLSLOptions.td | 2 + lib/DxcSupport/HLSLOptions.cpp | 1 + .../clang/tools/libclang/dxcrewriteunused.cpp | 211 ++++++++++++++++++ 4 files changed, 215 insertions(+) diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index 31ca3d1c14..ac1b311e1f 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -103,6 +103,7 @@ class DxcDefines { struct RewriterOpts { bool Unchanged = false; // OPT_rw_unchanged + bool ConsistentBindings = false; // OPT_rw_consistent_bindings bool SkipFunctionBody = false; // OPT_rw_skip_function_body bool SkipStatic = false; // OPT_rw_skip_static bool GlobalExternByDefault = false; // OPT_rw_global_extern_by_default diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index 58f6bdfbf3..fb597b8460 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -563,6 +563,8 @@ def nologo : Flag<["-", "/"], "nologo">, Group, Flags<[DriverOpt def rw_unchanged : Flag<["-", "/"], "unchanged">, Group, Flags<[RewriteOption]>, HelpText<"Rewrite HLSL, without changes.">; +def rw_consistent_bindings : Flag<["-", "/"], "consistent-bindings">, Group, Flags<[RewriteOption]>, + HelpText<"Generate bindings for registers that aren't fully qualified (to have consistent bindings).">; def rw_skip_function_body : Flag<["-", "/"], "skip-fn-body">, Group, Flags<[RewriteOption]>, HelpText<"Translate function definitions to declarations">; def rw_skip_static : Flag<["-", "/"], "skip-static">, Group, Flags<[RewriteOption]>, diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index eb071eb0a6..638cbf0ad8 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -1349,6 +1349,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, // Rewriter Options if (flagsToInclude & hlsl::options::RewriteOption) { opts.RWOpt.Unchanged = Args.hasFlag(OPT_rw_unchanged, OPT_INVALID, false); + opts.RWOpt.ConsistentBindings = Args.hasFlag(OPT_rw_consistent_bindings, OPT_INVALID, false); opts.RWOpt.SkipFunctionBody = Args.hasFlag(OPT_rw_skip_function_body, OPT_INVALID, false); opts.RWOpt.SkipStatic = diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index c29854077b..2515f9d7c6 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -12,6 +12,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/HlslTypes.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" @@ -1032,6 +1033,212 @@ static void RemoveStaticDecls(DeclContext &Ctx) { } } +struct ResourceKey { + + uint32_t space; + DXIL::ResourceClass resourceClass; + + bool operator==(const ResourceKey &other) const { + return space == other.space && resourceClass == other.resourceClass; + } +}; + +namespace llvm { +template<> +struct DenseMapInfo { + static inline ResourceKey getEmptyKey() { + return { ~0u, DXIL::ResourceClass::Invalid }; + } + static inline ResourceKey getTombstoneKey() { + return { ~0u - 1, DXIL::ResourceClass::Invalid }; + } + static unsigned getHashValue(const ResourceKey &K) { + return llvm::hash_combine(K.space, uint32_t(K.resourceClass)); + } + static bool isEqual(const ResourceKey &LHS, const ResourceKey &RHS) { + return LHS.space == RHS.space && LHS.resourceClass == RHS.resourceClass; + } +}; +} // namespace llvm + +using RegisterRange = std::pair; //(startReg, count) +using RegisterMap = llvm::DenseMap>; + +//Find gap in register list and fill it + +uint32_t FillNextRegister(llvm::SmallVector &ranges, + uint32_t arraySize) { + + if (ranges.empty()) { + ranges.push_back({ 0, arraySize }); + return 0; + } + + size_t i = 0, j = ranges.size(); + size_t curr = 0; + + for (; i < j; ++i) { + + const RegisterRange& range = ranges[i]; + + if (range.first - curr >= arraySize) { + ranges.insert(ranges.begin() + i, RegisterRange{curr, arraySize}); + return curr; + } + + curr = range.first + range.second; + } + + ranges.emplace_back(RegisterRange{curr, arraySize}); + return curr; +} + +//Insert in the right place (keep sorted) + +void FillRegisterAt(llvm::SmallVector &ranges, + uint32_t registerNr, uint32_t arraySize, + clang::DiagnosticsEngine &diags, const SourceLocation& location) { + + size_t i = 0, j = ranges.size(); + + for (; i < j; ++i) { + + const RegisterRange& range = ranges[i]; + + if (range.first > registerNr) { + + if (registerNr + arraySize > range.first) { + diags.Report(location, diag::err_hlsl_register_semantics_conflicting); + return; + } + + ranges.insert(ranges.begin() + i, RegisterRange{ registerNr, arraySize }); + break; + } + + if (range.first + range.second > registerNr) { + diags.Report(location, diag::err_hlsl_register_semantics_conflicting); + return; + } + } + + if (i == j) + ranges.emplace_back(RegisterRange{registerNr, arraySize}); +} + +static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpace) { + + clang::DiagnosticsEngine &Diags = + Ctx.getParentASTContext().getDiagnostics(); + + RegisterMap map; + DenseSet> unresolvedRegisters; + + //Fill up map with fully qualified registers to avoid colliding with them later + + for (auto it = Ctx.decls_begin(); it != Ctx.decls_end(); ++it) { + + VarDecl *VD = dyn_cast(*it); + + if (!VD) + continue; + + HLSLResourceAttr *resource = VD->getAttr(); + + if (!resource) + continue; + + uint32_t arraySize = 1; + + if (const ConstantArrayType *arr = dyn_cast(VD->getType())) + arraySize = arr->getSize().getZExtValue(); + + const ArrayRef &UA = VD->getUnusualAnnotations(); + + bool qualified = false; + RegisterAssignment *reg = nullptr; + + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { + + if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) + continue; + + reg = cast(*It); + + if (!reg->RegisterType) //Unqualified register assignment + break; + + uint32_t space = reg->RegisterSpace.hasValue() + ? reg->RegisterSpace.getValue() + : autoBindingSpace; + + qualified = true; + FillRegisterAt(map[ResourceKey{space, resource->getResClass()}], + reg->RegisterNumber, arraySize, Diags, VD->getLocation()); + break; + } + + if (!qualified) + unresolvedRegisters.insert({VD, reg}); + } + + //Resolve unresolved registers (while avoiding collisions) + + for (const auto& [VD, reg] : unresolvedRegisters) { + + HLSLResourceAttr *resource = VD->getAttr(); + + uint32_t arraySize = 1; + + if (const ConstantArrayType *arr = dyn_cast(VD->getType())) + arraySize = arr->getSize().getZExtValue(); + + char prefix = 't'; + + switch (resource->getResClass()) { + + case DXIL::ResourceClass::Sampler: + prefix = 's'; + break; + + case DXIL::ResourceClass::CBuffer: + prefix = 'b'; + break; + + case DXIL::ResourceClass::UAV: + prefix = 'u'; + break; + } + + uint32_t space = reg ? reg->RegisterSpace.getValue() : autoBindingSpace; + uint32_t registerNr = FillNextRegister(map[ResourceKey{ space, resource->getResClass() }], arraySize); + + if (reg) + { + reg->RegisterType = prefix; + reg->RegisterNumber = registerNr; + reg->setIsValid(true); + } + else + { + hlsl::RegisterAssignment r; //Keep space empty to ensure space overrides still work fine + r.RegisterNumber = registerNr; + r.RegisterType = prefix; + r.setIsValid(true); + + const ArrayRef &UA = + VD->getUnusualAnnotations(); + + SmallVector newVec; + newVec.append(UA.begin(), UA.end()); + newVec.push_back(new (Ctx.getParentASTContext()) + hlsl::RegisterAssignment(r)); + + VD->setUnusualAnnotations(newVec); + } + } +} + static void GlobalVariableAsExternByDefault(DeclContext &Ctx) { for (auto it = Ctx.decls_begin(); it != Ctx.decls_end();) { auto cur = it++; @@ -1065,6 +1272,10 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, TranslationUnitDecl *tu = astHelper.tu; + if (opts.RWOpt.ConsistentBindings) { + GenerateConsistentBindings(*tu, opts.AutoBindingSpace); + } + if (opts.RWOpt.SkipStatic && opts.RWOpt.SkipFunctionBody) { // Remove static functions and globals. RemoveStaticDecls(*tu); From 845427439c6d8ac51c2b0170472f2c19b697cc47 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 15 Jul 2025 19:42:55 +0200 Subject: [PATCH 002/126] Option -consistent-bindings now properly generates bindings for not fully qualified registers. --- tools/clang/include/clang/AST/HlslTypes.h | 1 + tools/clang/lib/AST/HlslTypes.cpp | 8 +++ .../clang/tools/libclang/dxcrewriteunused.cpp | 51 +++++++++++-------- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/tools/clang/include/clang/AST/HlslTypes.h b/tools/clang/include/clang/AST/HlslTypes.h index 43c1effdb8..2caa408b08 100644 --- a/tools/clang/include/clang/AST/HlslTypes.h +++ b/tools/clang/include/clang/AST/HlslTypes.h @@ -497,6 +497,7 @@ bool IsHLSLNumericOrAggregateOfNumericType(clang::QualType type); bool IsHLSLCopyableAnnotatableRecord(clang::QualType QT); bool IsHLSLBuiltinRayAttributeStruct(clang::QualType QT); bool IsHLSLAggregateType(clang::QualType type); +hlsl::DXIL::ResourceClass GetHLSLResourceClass(clang::QualType type); clang::QualType GetHLSLResourceResultType(clang::QualType type); clang::QualType GetHLSLNodeIOResultType(clang::ASTContext &astContext, clang::QualType type); diff --git a/tools/clang/lib/AST/HlslTypes.cpp b/tools/clang/lib/AST/HlslTypes.cpp index 00c18a81a9..8c35e2eb59 100644 --- a/tools/clang/lib/AST/HlslTypes.cpp +++ b/tools/clang/lib/AST/HlslTypes.cpp @@ -524,6 +524,14 @@ bool IsHLSLResourceType(clang::QualType type) { return false; } +hlsl::DXIL::ResourceClass GetHLSLResourceClass(clang::QualType type) { + + if (HLSLResourceAttr* attr = getAttr(type)) + return attr->getResClass(); + + return hlsl::DXIL::ResourceClass::Invalid; +} + bool IsHLSLHitObjectType(QualType type) { return nullptr != getAttr(type); } diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 2515f9d7c6..23ee3935c9 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1132,7 +1132,7 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa Ctx.getParentASTContext().getDiagnostics(); RegisterMap map; - DenseSet> unresolvedRegisters; + llvm::SmallVector, 8> unresolvedRegisters; //Fill up map with fully qualified registers to avoid colliding with them later @@ -1143,15 +1143,18 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa if (!VD) continue; - HLSLResourceAttr *resource = VD->getAttr(); - - if (!resource) - continue; - uint32_t arraySize = 1; + QualType type = VD->getType(); - if (const ConstantArrayType *arr = dyn_cast(VD->getType())) + if (const ConstantArrayType *arr = dyn_cast(VD->getType())) { arraySize = arr->getSize().getZExtValue(); + type = arr->getElementType(); + } + + if (!IsHLSLResourceType(type)) + continue; + + hlsl::DXIL::ResourceClass resClass = GetHLSLResourceClass(type); const ArrayRef &UA = VD->getUnusualAnnotations(); @@ -1173,29 +1176,32 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa : autoBindingSpace; qualified = true; - FillRegisterAt(map[ResourceKey{space, resource->getResClass()}], + FillRegisterAt(map[ResourceKey{space, resClass}], reg->RegisterNumber, arraySize, Diags, VD->getLocation()); break; } if (!qualified) - unresolvedRegisters.insert({VD, reg}); + unresolvedRegisters.emplace_back(std::pair{VD, reg}); } //Resolve unresolved registers (while avoiding collisions) for (const auto& [VD, reg] : unresolvedRegisters) { - HLSLResourceAttr *resource = VD->getAttr(); - uint32_t arraySize = 1; + QualType type = VD->getType(); - if (const ConstantArrayType *arr = dyn_cast(VD->getType())) + if (const ConstantArrayType *arr = dyn_cast(VD->getType())) { arraySize = arr->getSize().getZExtValue(); + type = arr->getElementType(); + } + + hlsl::DXIL::ResourceClass resClass = GetHLSLResourceClass(type); char prefix = 't'; - switch (resource->getResClass()) { + switch (resClass) { case DXIL::ResourceClass::Sampler: prefix = 's'; @@ -1211,7 +1217,8 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa } uint32_t space = reg ? reg->RegisterSpace.getValue() : autoBindingSpace; - uint32_t registerNr = FillNextRegister(map[ResourceKey{ space, resource->getResClass() }], arraySize); + uint32_t registerNr = + FillNextRegister(map[ResourceKey{space, resClass}], arraySize); if (reg) { @@ -1226,15 +1233,19 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa r.RegisterType = prefix; r.setIsValid(true); + llvm::SmallVector annotations; + const ArrayRef &UA = VD->getUnusualAnnotations(); - SmallVector newVec; - newVec.append(UA.begin(), UA.end()); - newVec.push_back(new (Ctx.getParentASTContext()) - hlsl::RegisterAssignment(r)); + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) + annotations.emplace_back(*It); + + annotations.push_back(::new (Ctx.getParentASTContext()) + hlsl::RegisterAssignment(r)); - VD->setUnusualAnnotations(newVec); + VD->setUnusualAnnotations(UnusualAnnotation::CopyToASTContextArray( + Ctx.getParentASTContext(), annotations.data(), annotations.size())); } } } @@ -1294,7 +1305,7 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, opts.RWOpt.RemoveUnusedFunctions, w); if (FAILED(hr)) return hr; - } else { + } else if(!opts.RWOpt.ConsistentBindings) { o << "// Rewrite unchanged result:\n"; } From f60c594eae64fb5ee3204962e0a3215606d8bfa4 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 15 Jul 2025 21:41:16 +0200 Subject: [PATCH 003/126] Added a test for generating consistent bindings and changed tests to allow passing different rewriter flags. Also added support for cbuffer auto bindings. --- .../HLSL/rewriter/consistent_bindings.hlsl | 48 +++++++ .../consistent_bindings_gold.hlsl | 49 +++++++ .../clang/tools/libclang/dxcrewriteunused.cpp | 124 +++++++++++------- tools/clang/unittests/HLSL/RewriterTest.cpp | 29 ++-- 4 files changed, 191 insertions(+), 59 deletions(-) create mode 100644 tools/clang/test/HLSL/rewriter/consistent_bindings.hlsl create mode 100644 tools/clang/test/HLSL/rewriter/correct_rewrites/consistent_bindings_gold.hlsl diff --git a/tools/clang/test/HLSL/rewriter/consistent_bindings.hlsl b/tools/clang/test/HLSL/rewriter/consistent_bindings.hlsl new file mode 100644 index 0000000000..e12eed0789 --- /dev/null +++ b/tools/clang/test/HLSL/rewriter/consistent_bindings.hlsl @@ -0,0 +1,48 @@ +//UAV + +RWByteAddressBuffer output1; +RWByteAddressBuffer output2; +RWByteAddressBuffer output3 : register(u0); +RWByteAddressBuffer output4 : register(space1); +RWByteAddressBuffer output5 : SEMA; +RWByteAddressBuffer output6; +RWByteAddressBuffer output7 : register(u1); +RWByteAddressBuffer output8[12] : register(u3); +RWByteAddressBuffer output9[12]; +RWByteAddressBuffer output10[33] : register(space1); +RWByteAddressBuffer output11[33] : register(space2); +RWByteAddressBuffer output12[33] : register(u0, space2); + +//SRV + +StructuredBuffer test; +ByteAddressBuffer input13 : SEMA; +ByteAddressBuffer input14; +ByteAddressBuffer input15 : register(t0); +ByteAddressBuffer input16[12] : register(t3); +ByteAddressBuffer input17[2] : register(space1); +ByteAddressBuffer input18[12] : register(t1, space1); +ByteAddressBuffer input19[3] : register(space1); +ByteAddressBuffer input20 : register(space1); + +//Sampler + +SamplerState sampler0; +SamplerState sampler1; +SamplerState sampler2 : register(s0); +SamplerState sampler3 : register(space1); +SamplerState sampler4 : register(s0, space1); + +//CBV + +cbuffer test : register(b0) { float a; }; +cbuffer test2 { float b; }; +cbuffer test3 : register(space1) { float c; }; +cbuffer test4 : register(space1) { float d; }; + +float e; + +[numthreads(16, 16, 1)] +void main(uint id : SV_DispatchThreadID) { + output2.Store(id * 4, 1); //Only use 1 output, but this won't result into output2 receiving wrong bindings +} diff --git a/tools/clang/test/HLSL/rewriter/correct_rewrites/consistent_bindings_gold.hlsl b/tools/clang/test/HLSL/rewriter/correct_rewrites/consistent_bindings_gold.hlsl new file mode 100644 index 0000000000..4c2810e9f4 --- /dev/null +++ b/tools/clang/test/HLSL/rewriter/correct_rewrites/consistent_bindings_gold.hlsl @@ -0,0 +1,49 @@ +RWByteAddressBuffer output1 : register(u2); +RWByteAddressBuffer output2 : register(u15); +RWByteAddressBuffer output3 : register(u0); +RWByteAddressBuffer output4 : register(u0, space1); +RWByteAddressBuffer output5 : SEMA : register(u16); +RWByteAddressBuffer output6 : register(u17); +RWByteAddressBuffer output7 : register(u1); +RWByteAddressBuffer output8[12] : register(u3); +RWByteAddressBuffer output9[12] : register(u18); +RWByteAddressBuffer output10[33] : register(u1, space1); +RWByteAddressBuffer output11[33] : register(u33, space2); +RWByteAddressBuffer output12[33] : register(u0, space2); +StructuredBuffer test : register(t1); +ByteAddressBuffer input13 : SEMA : register(t2); +ByteAddressBuffer input14 : register(t15); +ByteAddressBuffer input15 : register(t0); +ByteAddressBuffer input16[12] : register(t3); +ByteAddressBuffer input17[2] : register(t13, space1); +ByteAddressBuffer input18[12] : register(t1, space1); +ByteAddressBuffer input19[3] : register(t15, space1); +ByteAddressBuffer input20 : register(t0, space1); +SamplerState sampler0 : register(s1); +SamplerState sampler1 : register(s2); +SamplerState sampler2 : register(s0); +SamplerState sampler3 : register(s1, space1); +SamplerState sampler4 : register(s0, space1); +cbuffer test : register(b0) { + const float a; +} +; +cbuffer test2 : register(b1) { + const float b; +} +; +cbuffer test3 : register(b0, space1) { + const float c; +} +; +cbuffer test4 : register(b1, space1) { + const float d; +} +; +const float e; +[numthreads(16, 16, 1)] +void main(uint id : SV_DispatchThreadID) { + output2.Store(id * 4, 1); +} + + diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 23ee3935c9..b92d04ebde 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1064,6 +1064,15 @@ struct DenseMapInfo { using RegisterRange = std::pair; //(startReg, count) using RegisterMap = llvm::DenseMap>; +struct UnresolvedRegister { + hlsl::DXIL::ResourceClass cls; + uint32_t arraySize; + RegisterAssignment *reg; + NamedDecl *ND; +}; + +using UnresolvedRegisters = llvm::SmallVector; + //Find gap in register list and fill it uint32_t FillNextRegister(llvm::SmallVector &ranges, @@ -1126,23 +1135,74 @@ void FillRegisterAt(llvm::SmallVector &ranges, ranges.emplace_back(RegisterRange{registerNr, arraySize}); } +static void RegisterBinding( + NamedDecl *ND, + UnresolvedRegisters& unresolvedRegisters, + RegisterMap& map, + hlsl::DXIL::ResourceClass cls, + uint32_t arraySize, + clang::DiagnosticsEngine &Diags, + uint32_t autoBindingSpace +) { + + const ArrayRef &UA = + ND->getUnusualAnnotations(); + + bool qualified = false; + RegisterAssignment *reg = nullptr; + + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { + + if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) + continue; + + reg = cast(*It); + + if (!reg->RegisterType) //Unqualified register assignment + break; + + uint32_t space = reg->RegisterSpace.hasValue() + ? reg->RegisterSpace.getValue() + : autoBindingSpace; + + qualified = true; + FillRegisterAt(map[ResourceKey{space, cls }], + reg->RegisterNumber, arraySize, Diags, ND->getLocation()); + break; + } + + if (!qualified) + unresolvedRegisters.emplace_back(UnresolvedRegister{cls, arraySize, reg, ND}); +} + static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpace) { clang::DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); RegisterMap map; - llvm::SmallVector, 8> unresolvedRegisters; + UnresolvedRegisters unresolvedRegisters; //Fill up map with fully qualified registers to avoid colliding with them later for (auto it = Ctx.decls_begin(); it != Ctx.decls_end(); ++it) { - VarDecl *VD = dyn_cast(*it); + //CBuffer has special logic, since it's not technically + + if (HLSLBufferDecl *CBuffer = dyn_cast(*it)) { + RegisterBinding(CBuffer, unresolvedRegisters, map, + hlsl::DXIL::ResourceClass::CBuffer, 1, Diags, + autoBindingSpace); + continue; + } + + ValueDecl *VD = dyn_cast(*it); if (!VD) continue; + std::string test = VD->getName(); + uint32_t arraySize = 1; QualType type = VD->getType(); @@ -1154,50 +1214,16 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa if (!IsHLSLResourceType(type)) continue; - hlsl::DXIL::ResourceClass resClass = GetHLSLResourceClass(type); - - const ArrayRef &UA = VD->getUnusualAnnotations(); - - bool qualified = false; - RegisterAssignment *reg = nullptr; - - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { - - if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) - continue; - - reg = cast(*It); - - if (!reg->RegisterType) //Unqualified register assignment - break; - - uint32_t space = reg->RegisterSpace.hasValue() - ? reg->RegisterSpace.getValue() - : autoBindingSpace; - - qualified = true; - FillRegisterAt(map[ResourceKey{space, resClass}], - reg->RegisterNumber, arraySize, Diags, VD->getLocation()); - break; - } - - if (!qualified) - unresolvedRegisters.emplace_back(std::pair{VD, reg}); + RegisterBinding(VD, unresolvedRegisters, map, GetHLSLResourceClass(type), + arraySize, Diags, autoBindingSpace); } //Resolve unresolved registers (while avoiding collisions) - for (const auto& [VD, reg] : unresolvedRegisters) { + for (const UnresolvedRegister& reg : unresolvedRegisters) { - uint32_t arraySize = 1; - QualType type = VD->getType(); - - if (const ConstantArrayType *arr = dyn_cast(VD->getType())) { - arraySize = arr->getSize().getZExtValue(); - type = arr->getElementType(); - } - - hlsl::DXIL::ResourceClass resClass = GetHLSLResourceClass(type); + uint32_t arraySize = reg.arraySize; + hlsl::DXIL::ResourceClass resClass = reg.cls; char prefix = 't'; @@ -1216,15 +1242,17 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa break; } - uint32_t space = reg ? reg->RegisterSpace.getValue() : autoBindingSpace; + uint32_t space = + reg.reg ? reg.reg->RegisterSpace.getValue() : autoBindingSpace; + uint32_t registerNr = FillNextRegister(map[ResourceKey{space, resClass}], arraySize); - if (reg) + if (reg.reg) { - reg->RegisterType = prefix; - reg->RegisterNumber = registerNr; - reg->setIsValid(true); + reg.reg->RegisterType = prefix; + reg.reg->RegisterNumber = registerNr; + reg.reg->setIsValid(true); } else { @@ -1236,7 +1264,7 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa llvm::SmallVector annotations; const ArrayRef &UA = - VD->getUnusualAnnotations(); + reg.ND->getUnusualAnnotations(); for (auto It = UA.begin(), E = UA.end(); It != E; ++It) annotations.emplace_back(*It); @@ -1244,7 +1272,7 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa annotations.push_back(::new (Ctx.getParentASTContext()) hlsl::RegisterAssignment(r)); - VD->setUnusualAnnotations(UnusualAnnotation::CopyToASTContextArray( + reg.ND->setUnusualAnnotations(UnusualAnnotation::CopyToASTContextArray( Ctx.getParentASTContext(), annotations.data(), annotations.size())); } } diff --git a/tools/clang/unittests/HLSL/RewriterTest.cpp b/tools/clang/unittests/HLSL/RewriterTest.cpp index 613c8561a3..00125275ff 100644 --- a/tools/clang/unittests/HLSL/RewriterTest.cpp +++ b/tools/clang/unittests/HLSL/RewriterTest.cpp @@ -102,6 +102,7 @@ class RewriterTest : public ::testing::Test { TEST_METHOD(RunExtractUniforms) TEST_METHOD(RunGlobalsUsedInMethod) TEST_METHOD(RunRewriterFails) + TEST_METHOD(GenerateConsistentBindings) dxc::DxcDllSupport m_dllSupport; CComPtr m_pIncludeHandler; @@ -126,16 +127,18 @@ class RewriterTest : public ::testing::Test { ppBlob)); } - VerifyResult CheckVerifies(LPCWSTR path, LPCWSTR goldPath) { + VerifyResult CheckVerifies(LPCWSTR path, LPCWSTR goldPath, + const llvm::SmallVector &args = { L"-HV", L"2016" }) { CComPtr pRewriter; VERIFY_SUCCEEDED(CreateRewriter(&pRewriter)); - return CheckVerifies(pRewriter, path, goldPath); + return CheckVerifies(pRewriter, path, goldPath, args); } VerifyResult CheckVerifies(IDxcRewriter *pRewriter, LPCWSTR path, - LPCWSTR goldPath) { + LPCWSTR goldPath, + const llvm::SmallVector &args = { L"-HV", L"2016" }) { CComPtr pRewriteResult; - RewriteCompareGold(path, goldPath, &pRewriteResult, pRewriter); + RewriteCompareGold(path, goldPath, &pRewriteResult, pRewriter, args); VerifyResult toReturn; @@ -165,9 +168,9 @@ class RewriterTest : public ::testing::Test { return S_OK; } - VerifyResult CheckVerifiesHLSL(LPCWSTR name, LPCWSTR goldName) { + VerifyResult CheckVerifiesHLSL(LPCWSTR name, LPCWSTR goldName, const llvm::SmallVector &args = { L"-HV", L"2016" }) { return CheckVerifies(GetPathToHlslDataFile(name).c_str(), - GetPathToHlslDataFile(goldName).c_str()); + GetPathToHlslDataFile(goldName).c_str(), args); } struct FileWithBlob { @@ -210,7 +213,8 @@ class RewriterTest : public ::testing::Test { void RewriteCompareGold(LPCWSTR path, LPCWSTR goldPath, IDxcOperationResult **ppResult, - IDxcRewriter *rewriter) { + IDxcRewriter *rewriter, + const llvm::SmallVector &args = {}) { // Get the source text from a file FileWithBlob source(m_dllSupport, path); @@ -218,13 +222,11 @@ class RewriterTest : public ::testing::Test { DxcDefine myDefines[myDefinesCount] = { {L"myDefine", L"2"}, {L"myDefine3", L"1994"}, {L"myDefine4", nullptr}}; - LPCWSTR args[] = {L"-HV", L"2016"}; - CComPtr rewriter2; VERIFY_SUCCEEDED(rewriter->QueryInterface(&rewriter2)); // Run rewrite unchanged on the source code VERIFY_SUCCEEDED(rewriter2->RewriteWithOptions( - source.BlobEncoding, path, args, _countof(args), myDefines, + source.BlobEncoding, path, (LPCWSTR*) args.data(), (uint32_t) args.size(), myDefines, myDefinesCount, nullptr, ppResult)); // check for compilation errors @@ -329,7 +331,7 @@ TEST_F(RewriterTest, RunArrayLength) { TEST_F(RewriterTest, RunAttributes) { CheckVerifiesHLSL(L"rewriter\\attributes_noerr.hlsl", - L"rewriter\\correct_rewrites\\attributes_gold.hlsl"); + L"rewriter\\correct_rewrites\\attributes_gold.hlsl"); } TEST_F(RewriterTest, RunAnonymousStruct) { @@ -462,6 +464,11 @@ TEST_F(RewriterTest, RunSpirv) { VERIFY_IS_TRUE(strResult.find("namespace vk") == std::string::npos); } +TEST_F(RewriterTest, GenerateConsistentBindings) { + CheckVerifiesHLSL(L"rewriter\\consistent_bindings.hlsl", + L"rewriter\\correct_rewrites\\consistent_bindings_gold.hlsl", { L"-HV", L"2016", L"-consistent-bindings" }); +} + TEST_F(RewriterTest, RunStructMethods) { CheckVerifiesHLSL(L"rewriter\\struct-methods.hlsl", L"rewriter\\correct_rewrites\\struct-methods_gold.hlsl"); From 74283d158717e300116cbf26fb0b943bd4b5c51a Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 16 Jul 2025 15:35:53 +0200 Subject: [PATCH 004/126] Applied clang format --- lib/DxcSupport/HLSLOptions.cpp | 3 +- tools/clang/lib/AST/HlslTypes.cpp | 4 +- .../clang/tools/libclang/dxcrewriteunused.cpp | 145 +++++++++--------- tools/clang/unittests/HLSL/RewriterTest.cpp | 25 +-- 4 files changed, 90 insertions(+), 87 deletions(-) diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index 638cbf0ad8..c733b2a633 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -1349,7 +1349,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, // Rewriter Options if (flagsToInclude & hlsl::options::RewriteOption) { opts.RWOpt.Unchanged = Args.hasFlag(OPT_rw_unchanged, OPT_INVALID, false); - opts.RWOpt.ConsistentBindings = Args.hasFlag(OPT_rw_consistent_bindings, OPT_INVALID, false); + opts.RWOpt.ConsistentBindings = + Args.hasFlag(OPT_rw_consistent_bindings, OPT_INVALID, false); opts.RWOpt.SkipFunctionBody = Args.hasFlag(OPT_rw_skip_function_body, OPT_INVALID, false); opts.RWOpt.SkipStatic = diff --git a/tools/clang/lib/AST/HlslTypes.cpp b/tools/clang/lib/AST/HlslTypes.cpp index 8c35e2eb59..9748e13069 100644 --- a/tools/clang/lib/AST/HlslTypes.cpp +++ b/tools/clang/lib/AST/HlslTypes.cpp @@ -526,8 +526,8 @@ bool IsHLSLResourceType(clang::QualType type) { hlsl::DXIL::ResourceClass GetHLSLResourceClass(clang::QualType type) { - if (HLSLResourceAttr* attr = getAttr(type)) - return attr->getResClass(); + if (HLSLResourceAttr *attr = getAttr(type)) + return attr->getResClass(); return hlsl::DXIL::ResourceClass::Invalid; } diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index b92d04ebde..bf7cf1e702 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -11,8 +11,8 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/HlslTypes.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" @@ -1044,13 +1044,12 @@ struct ResourceKey { }; namespace llvm { -template<> -struct DenseMapInfo { +template <> struct DenseMapInfo { static inline ResourceKey getEmptyKey() { - return { ~0u, DXIL::ResourceClass::Invalid }; + return {~0u, DXIL::ResourceClass::Invalid}; } static inline ResourceKey getTombstoneKey() { - return { ~0u - 1, DXIL::ResourceClass::Invalid }; + return {~0u - 1, DXIL::ResourceClass::Invalid}; } static unsigned getHashValue(const ResourceKey &K) { return llvm::hash_combine(K.space, uint32_t(K.resourceClass)); @@ -1062,7 +1061,8 @@ struct DenseMapInfo { } // namespace llvm using RegisterRange = std::pair; //(startReg, count) -using RegisterMap = llvm::DenseMap>; +using RegisterMap = + llvm::DenseMap>; struct UnresolvedRegister { hlsl::DXIL::ResourceClass cls; @@ -1073,13 +1073,13 @@ struct UnresolvedRegister { using UnresolvedRegisters = llvm::SmallVector; -//Find gap in register list and fill it +// Find gap in register list and fill it uint32_t FillNextRegister(llvm::SmallVector &ranges, uint32_t arraySize) { - + if (ranges.empty()) { - ranges.push_back({ 0, arraySize }); + ranges.push_back({0, arraySize}); return 0; } @@ -1088,7 +1088,7 @@ uint32_t FillNextRegister(llvm::SmallVector &ranges, for (; i < j; ++i) { - const RegisterRange& range = ranges[i]; + const RegisterRange &range = ranges[i]; if (range.first - curr >= arraySize) { ranges.insert(ranges.begin() + i, RegisterRange{curr, arraySize}); @@ -1102,32 +1102,33 @@ uint32_t FillNextRegister(llvm::SmallVector &ranges, return curr; } -//Insert in the right place (keep sorted) +// Insert in the right place (keep sorted) void FillRegisterAt(llvm::SmallVector &ranges, - uint32_t registerNr, uint32_t arraySize, - clang::DiagnosticsEngine &diags, const SourceLocation& location) { + uint32_t registerNr, uint32_t arraySize, + clang::DiagnosticsEngine &diags, + const SourceLocation &location) { size_t i = 0, j = ranges.size(); for (; i < j; ++i) { - const RegisterRange& range = ranges[i]; + const RegisterRange &range = ranges[i]; if (range.first > registerNr) { - + if (registerNr + arraySize > range.first) { diags.Report(location, diag::err_hlsl_register_semantics_conflicting); return; } - ranges.insert(ranges.begin() + i, RegisterRange{ registerNr, arraySize }); + ranges.insert(ranges.begin() + i, RegisterRange{registerNr, arraySize}); break; } if (range.first + range.second > registerNr) { - diags.Report(location, diag::err_hlsl_register_semantics_conflicting); - return; + diags.Report(location, diag::err_hlsl_register_semantics_conflicting); + return; } } @@ -1135,64 +1136,61 @@ void FillRegisterAt(llvm::SmallVector &ranges, ranges.emplace_back(RegisterRange{registerNr, arraySize}); } -static void RegisterBinding( - NamedDecl *ND, - UnresolvedRegisters& unresolvedRegisters, - RegisterMap& map, - hlsl::DXIL::ResourceClass cls, - uint32_t arraySize, - clang::DiagnosticsEngine &Diags, - uint32_t autoBindingSpace -) { +static void RegisterBinding(NamedDecl *ND, + UnresolvedRegisters &unresolvedRegisters, + RegisterMap &map, hlsl::DXIL::ResourceClass cls, + uint32_t arraySize, clang::DiagnosticsEngine &Diags, + uint32_t autoBindingSpace) { - const ArrayRef &UA = - ND->getUnusualAnnotations(); + const ArrayRef &UA = ND->getUnusualAnnotations(); bool qualified = false; RegisterAssignment *reg = nullptr; for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { - if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) + if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) continue; - reg = cast(*It); + reg = cast(*It); - if (!reg->RegisterType) //Unqualified register assignment - break; + if (!reg->RegisterType) // Unqualified register assignment + break; - uint32_t space = reg->RegisterSpace.hasValue() - ? reg->RegisterSpace.getValue() - : autoBindingSpace; + uint32_t space = reg->RegisterSpace.hasValue() + ? reg->RegisterSpace.getValue() + : autoBindingSpace; - qualified = true; - FillRegisterAt(map[ResourceKey{space, cls }], - reg->RegisterNumber, arraySize, Diags, ND->getLocation()); - break; + qualified = true; + FillRegisterAt(map[ResourceKey{space, cls}], reg->RegisterNumber, arraySize, + Diags, ND->getLocation()); + break; } if (!qualified) - unresolvedRegisters.emplace_back(UnresolvedRegister{cls, arraySize, reg, ND}); + unresolvedRegisters.emplace_back( + UnresolvedRegister{cls, arraySize, reg, ND}); } -static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpace) { +static void GenerateConsistentBindings(DeclContext &Ctx, + uint32_t autoBindingSpace) { - clang::DiagnosticsEngine &Diags = - Ctx.getParentASTContext().getDiagnostics(); + clang::DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); RegisterMap map; UnresolvedRegisters unresolvedRegisters; - //Fill up map with fully qualified registers to avoid colliding with them later + // Fill up map with fully qualified registers to avoid colliding with them + // later for (auto it = Ctx.decls_begin(); it != Ctx.decls_end(); ++it) { - //CBuffer has special logic, since it's not technically + // CBuffer has special logic, since it's not technically if (HLSLBufferDecl *CBuffer = dyn_cast(*it)) { RegisterBinding(CBuffer, unresolvedRegisters, map, - hlsl::DXIL::ResourceClass::CBuffer, 1, Diags, - autoBindingSpace); + hlsl::DXIL::ResourceClass::CBuffer, 1, Diags, + autoBindingSpace); continue; } @@ -1206,11 +1204,12 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa uint32_t arraySize = 1; QualType type = VD->getType(); - if (const ConstantArrayType *arr = dyn_cast(VD->getType())) { + if (const ConstantArrayType *arr = + dyn_cast(VD->getType())) { arraySize = arr->getSize().getZExtValue(); type = arr->getElementType(); } - + if (!IsHLSLResourceType(type)) continue; @@ -1218,9 +1217,9 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa arraySize, Diags, autoBindingSpace); } - //Resolve unresolved registers (while avoiding collisions) + // Resolve unresolved registers (while avoiding collisions) - for (const UnresolvedRegister& reg : unresolvedRegisters) { + for (const UnresolvedRegister ® : unresolvedRegisters) { uint32_t arraySize = reg.arraySize; hlsl::DXIL::ResourceClass resClass = reg.cls; @@ -1248,32 +1247,30 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t autoBindingSpa uint32_t registerNr = FillNextRegister(map[ResourceKey{space, resClass}], arraySize); - if (reg.reg) - { - reg.reg->RegisterType = prefix; - reg.reg->RegisterNumber = registerNr; - reg.reg->setIsValid(true); - } - else - { - hlsl::RegisterAssignment r; //Keep space empty to ensure space overrides still work fine - r.RegisterNumber = registerNr; - r.RegisterType = prefix; - r.setIsValid(true); + if (reg.reg) { + reg.reg->RegisterType = prefix; + reg.reg->RegisterNumber = registerNr; + reg.reg->setIsValid(true); + } else { + hlsl::RegisterAssignment + r; // Keep space empty to ensure space overrides still work fine + r.RegisterNumber = registerNr; + r.RegisterType = prefix; + r.setIsValid(true); - llvm::SmallVector annotations; + llvm::SmallVector annotations; - const ArrayRef &UA = - reg.ND->getUnusualAnnotations(); + const ArrayRef &UA = + reg.ND->getUnusualAnnotations(); - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) - annotations.emplace_back(*It); + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) + annotations.emplace_back(*It); - annotations.push_back(::new (Ctx.getParentASTContext()) - hlsl::RegisterAssignment(r)); + annotations.push_back(::new (Ctx.getParentASTContext()) + hlsl::RegisterAssignment(r)); - reg.ND->setUnusualAnnotations(UnusualAnnotation::CopyToASTContextArray( - Ctx.getParentASTContext(), annotations.data(), annotations.size())); + reg.ND->setUnusualAnnotations(UnusualAnnotation::CopyToASTContextArray( + Ctx.getParentASTContext(), annotations.data(), annotations.size())); } } } @@ -1333,7 +1330,7 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, opts.RWOpt.RemoveUnusedFunctions, w); if (FAILED(hr)) return hr; - } else if(!opts.RWOpt.ConsistentBindings) { + } else if (!opts.RWOpt.ConsistentBindings) { o << "// Rewrite unchanged result:\n"; } diff --git a/tools/clang/unittests/HLSL/RewriterTest.cpp b/tools/clang/unittests/HLSL/RewriterTest.cpp index 00125275ff..7adfd3f88e 100644 --- a/tools/clang/unittests/HLSL/RewriterTest.cpp +++ b/tools/clang/unittests/HLSL/RewriterTest.cpp @@ -128,15 +128,16 @@ class RewriterTest : public ::testing::Test { } VerifyResult CheckVerifies(LPCWSTR path, LPCWSTR goldPath, - const llvm::SmallVector &args = { L"-HV", L"2016" }) { + const llvm::SmallVector &args = { + L"-HV", L"2016"}) { CComPtr pRewriter; VERIFY_SUCCEEDED(CreateRewriter(&pRewriter)); return CheckVerifies(pRewriter, path, goldPath, args); } - VerifyResult CheckVerifies(IDxcRewriter *pRewriter, LPCWSTR path, - LPCWSTR goldPath, - const llvm::SmallVector &args = { L"-HV", L"2016" }) { + VerifyResult + CheckVerifies(IDxcRewriter *pRewriter, LPCWSTR path, LPCWSTR goldPath, + const llvm::SmallVector &args = {L"-HV", L"2016"}) { CComPtr pRewriteResult; RewriteCompareGold(path, goldPath, &pRewriteResult, pRewriter, args); @@ -168,7 +169,9 @@ class RewriterTest : public ::testing::Test { return S_OK; } - VerifyResult CheckVerifiesHLSL(LPCWSTR name, LPCWSTR goldName, const llvm::SmallVector &args = { L"-HV", L"2016" }) { + VerifyResult CheckVerifiesHLSL(LPCWSTR name, LPCWSTR goldName, + const llvm::SmallVector &args = { + L"-HV", L"2016"}) { return CheckVerifies(GetPathToHlslDataFile(name).c_str(), GetPathToHlslDataFile(goldName).c_str(), args); } @@ -226,8 +229,8 @@ class RewriterTest : public ::testing::Test { VERIFY_SUCCEEDED(rewriter->QueryInterface(&rewriter2)); // Run rewrite unchanged on the source code VERIFY_SUCCEEDED(rewriter2->RewriteWithOptions( - source.BlobEncoding, path, (LPCWSTR*) args.data(), (uint32_t) args.size(), myDefines, - myDefinesCount, nullptr, ppResult)); + source.BlobEncoding, path, (LPCWSTR *)args.data(), + (uint32_t)args.size(), myDefines, myDefinesCount, nullptr, ppResult)); // check for compilation errors HRESULT hrStatus; @@ -331,7 +334,7 @@ TEST_F(RewriterTest, RunArrayLength) { TEST_F(RewriterTest, RunAttributes) { CheckVerifiesHLSL(L"rewriter\\attributes_noerr.hlsl", - L"rewriter\\correct_rewrites\\attributes_gold.hlsl"); + L"rewriter\\correct_rewrites\\attributes_gold.hlsl"); } TEST_F(RewriterTest, RunAnonymousStruct) { @@ -465,8 +468,10 @@ TEST_F(RewriterTest, RunSpirv) { } TEST_F(RewriterTest, GenerateConsistentBindings) { - CheckVerifiesHLSL(L"rewriter\\consistent_bindings.hlsl", - L"rewriter\\correct_rewrites\\consistent_bindings_gold.hlsl", { L"-HV", L"2016", L"-consistent-bindings" }); + CheckVerifiesHLSL( + L"rewriter\\consistent_bindings.hlsl", + L"rewriter\\correct_rewrites\\consistent_bindings_gold.hlsl", + {L"-HV", L"2016", L"-consistent-bindings"}); } TEST_F(RewriterTest, RunStructMethods) { From 94bc9e99f7783923b0e4552339ead94bf6aa5998 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 2 Aug 2025 14:23:27 +0200 Subject: [PATCH 005/126] Added a 'reflect HLSL' argument to the rewriter (-reflect-hlsl). Currently it can build a mini AST out of the clang AST. The goal of this AST is to provide a simplified AST that is extremely easy for users to iterate over and is quite efficient. This AST can be used to supplement reflection from DXIL/SPIRV since this data disappears while lowering to DXIL/SPIRV; such as unused registers, struct definitions, enum definitions, annotations as well as source ranges of the symbols to allow jumping to symbols. All of this allows external tooling to more easily report errors while doing validation with reflection and would allow editors to show a simplified view of the symbols defined in the current file. It opens up a lot of possibilities for HLSL editors because there is simply more information available and avoids everyone from writing their own parser that isn't properly HLSL compliant. As an example for my own projects; I use my own parser to collect functions with annotations so I can handle compiling the relevant entries automatically and in my professional project a custom parser is used to obtain lots of information since shaders are used to guide the render library (such as providing visual scripting nodes that need to be consistent even if registers are compiled out). Currently only supporting namespaces, resources/registers, enums. TODO: Variables, nested arrays for registers, annotations, functions, body for functions, targeted -reflect-hlsl functions like -reflect-hlsl-functions to avoid a large AST, expose the generated reflection as a serialized blob and be able to use it as an interface from C++, enums should store members of Enum as nodes to allow source code inspection. EnumValues should just be int64_t[]. EnumValue should be relative to start value of Enum. --- include/dxc/Support/HLSLOptions.h | 1 + include/dxc/Support/HLSLOptions.td | 2 + include/dxc/dxctools.h | 90 +++ lib/DxcSupport/HLSLOptions.cpp | 2 + .../clang/tools/libclang/dxcrewriteunused.cpp | 693 +++++++++++++++++- 5 files changed, 778 insertions(+), 10 deletions(-) diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index ac1b311e1f..08777e5426 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -104,6 +104,7 @@ class DxcDefines { struct RewriterOpts { bool Unchanged = false; // OPT_rw_unchanged bool ConsistentBindings = false; // OPT_rw_consistent_bindings + bool ReflectHLSL = false; // OPT_rw_reflect_hlsl bool SkipFunctionBody = false; // OPT_rw_skip_function_body bool SkipStatic = false; // OPT_rw_skip_static bool GlobalExternByDefault = false; // OPT_rw_global_extern_by_default diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index fb597b8460..2fe689a244 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -565,6 +565,8 @@ def rw_unchanged : Flag<["-", "/"], "unchanged">, Group, Flag HelpText<"Rewrite HLSL, without changes.">; def rw_consistent_bindings : Flag<["-", "/"], "consistent-bindings">, Group, Flags<[RewriteOption]>, HelpText<"Generate bindings for registers that aren't fully qualified (to have consistent bindings).">; +def rw_reflect_hlsl : Flag<["-", "/"], "reflect-hlsl">, Group, Flags<[RewriteOption]>, + HelpText<"Reflect HLSL and generate consistent bindings.">; def rw_skip_function_body : Flag<["-", "/"], "skip-fn-body">, Group, Flags<[RewriteOption]>, HelpText<"Translate function definitions to declarations">; def rw_skip_static : Flag<["-", "/"], "skip-static">, Group, Flags<[RewriteOption]>, diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index bfdc0d86f7..b721611b29 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -70,4 +70,94 @@ struct IDxcRewriter2 : public IDxcRewriter { IDxcIncludeHandler *pIncludeHandler, IDxcOperationResult **ppResult) = 0; }; +//Expose HLSL reflection before DXIL/SPIRV generation. +//(Ideally ran after the preprocessed HLSL is obtained). +//This is useful to avoid custom parsers from reinventing the wheel. +//You could use it to find all entrypoints even if [shader("")] isn't used, +//Find struct/enum information, find out about optimized out registers, etc. + +struct D3D12_HLSL_REFLECTION_DESC { + UINT ConstantBufferCount; + UINT ResourceCount; + UINT FunctionCount; + UINT EnumCount; + UINT StructCount; +}; + +struct D3D12_HLSL_FUNCTION_DESC { + LPCSTR Name; // Function name + UINT FunctionParameterCount; // Number of logical parameters in the function + // signature (not including return) + BOOL HasReturn; // TRUE, if function returns a value, false - it is a + // subroutine +}; + +struct D3D12_HLSL_ENUM_DESC { + LPCSTR Name; + UINT ValueCount; +}; + +struct D3D12_HLSL_ENUM_VALUE { + LPCSTR Name; + INT64 Value; +}; + +typedef interface ID3D12ShaderReflectionConstantBuffer + ID3D12ShaderReflectionConstantBuffer; + +typedef struct _D3D12_SHADER_INPUT_BIND_DESC D3D12_SHADER_INPUT_BIND_DESC; +typedef interface ID3D12ShaderReflectionVariable ID3D12ShaderReflectionVariable; +typedef interface ID3D12FunctionParameterReflection ID3D12FunctionParameterReflection; +typedef interface ID3D12ShaderReflectionType ID3D12ShaderReflectionType; + +CROSS_PLATFORM_UUIDOF(IDxcHLSLReflection, "7016f834-ae85-4c86-a473-8c2c981dd370") +struct IDxcHLSLReflection : public IUnknown { + + STDMETHOD(QueryInterface)(THIS_ _In_ REFIID iid, _Out_ LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_HLSL_REFLECTION_DESC *pDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetConstantBufferByIndex)(THIS_ _In_ UINT Index) PURE; + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetConstantBufferByName)(THIS_ _In_ LPCSTR Name) PURE; + + STDMETHOD(GetResourceBindingDesc)(THIS_ _In_ UINT ResourceIndex, + _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE; + STDMETHOD(GetResourceBindingDescByName)(THIS_ _In_ LPCSTR Name, + _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE; + + STDMETHOD(GetFunctionDesc) + (THIS_ _In_ UINT FunctionIndex, + THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) PURE; + + // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. + STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) + (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE; + + STDMETHOD(GetStructTypeByIndex) + (THIS_ _In_ UINT StructIndex, + _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + + STDMETHOD(GetStructTypeByName) + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + + STDMETHOD(GetEnumDesc) + (THIS_ _In_ UINT EnumIndex, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; + + STDMETHOD(GetEnumDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; + + STDMETHOD(GetEnumValueByIndex) + (THIS_ _In_ UINT EnumIndex, _In_ UINT ValueIndex, + _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) PURE; + + STDMETHOD(GetAnnotationCount) + (THIS_ _In_ LPCSTR SymbolName, _Out_ UINT *pCount) PURE; + + STDMETHOD(GetAnnotationByIndex) + (THIS_ _In_ LPCSTR SymbolName, _In_ UINT Index, + _Outptr_result_z_ LPCSTR *ppAnnotationText) PURE; +}; + #endif diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index c733b2a633..535fae4c97 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -1351,6 +1351,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, opts.RWOpt.Unchanged = Args.hasFlag(OPT_rw_unchanged, OPT_INVALID, false); opts.RWOpt.ConsistentBindings = Args.hasFlag(OPT_rw_consistent_bindings, OPT_INVALID, false); + opts.RWOpt.ReflectHLSL = + Args.hasFlag(OPT_rw_reflect_hlsl, OPT_INVALID, false); opts.RWOpt.SkipFunctionBody = Args.hasFlag(OPT_rw_skip_function_body, OPT_INVALID, false); opts.RWOpt.SkipStatic = diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index bf7cf1e702..740ee16b57 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -12,6 +12,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/HlslTypes.h" +#include "clang/AST/Attr.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" @@ -45,6 +46,8 @@ #include "dxc/dxcapi.internal.h" #include "dxc/dxctools.h" +#include "d3d12shader.h" + // From dxcutil.h namespace dxcutil { bool IsAbsoluteOrCurDirRelative(const llvm::Twine &T); @@ -1075,6 +1078,8 @@ using UnresolvedRegisters = llvm::SmallVector; // Find gap in register list and fill it +//TODO: Niels, check multi dim arrays + uint32_t FillNextRegister(llvm::SmallVector &ranges, uint32_t arraySize) { @@ -1104,7 +1109,7 @@ uint32_t FillNextRegister(llvm::SmallVector &ranges, // Insert in the right place (keep sorted) -void FillRegisterAt(llvm::SmallVector &ranges, +void FillConsistentRegisterAt(llvm::SmallVector &ranges, uint32_t registerNr, uint32_t arraySize, clang::DiagnosticsEngine &diags, const SourceLocation &location) { @@ -1136,7 +1141,7 @@ void FillRegisterAt(llvm::SmallVector &ranges, ranges.emplace_back(RegisterRange{registerNr, arraySize}); } -static void RegisterBinding(NamedDecl *ND, +static void RegisterConsistentBinding(NamedDecl *ND, UnresolvedRegisters &unresolvedRegisters, RegisterMap &map, hlsl::DXIL::ResourceClass cls, uint32_t arraySize, clang::DiagnosticsEngine &Diags, @@ -1162,7 +1167,7 @@ static void RegisterBinding(NamedDecl *ND, : autoBindingSpace; qualified = true; - FillRegisterAt(map[ResourceKey{space, cls}], reg->RegisterNumber, arraySize, + FillConsistentRegisterAt(map[ResourceKey{space, cls}], reg->RegisterNumber, arraySize, Diags, ND->getLocation()); break; } @@ -1183,18 +1188,18 @@ static void GenerateConsistentBindings(DeclContext &Ctx, // Fill up map with fully qualified registers to avoid colliding with them // later - for (auto it = Ctx.decls_begin(); it != Ctx.decls_end(); ++it) { + for (Decl *it : Ctx.decls()) { // CBuffer has special logic, since it's not technically - if (HLSLBufferDecl *CBuffer = dyn_cast(*it)) { - RegisterBinding(CBuffer, unresolvedRegisters, map, + if (HLSLBufferDecl *CBuffer = dyn_cast(it)) { + RegisterConsistentBinding(CBuffer, unresolvedRegisters, map, hlsl::DXIL::ResourceClass::CBuffer, 1, Diags, autoBindingSpace); continue; } - ValueDecl *VD = dyn_cast(*it); + ValueDecl *VD = dyn_cast(it); if (!VD) continue; @@ -1213,7 +1218,7 @@ static void GenerateConsistentBindings(DeclContext &Ctx, if (!IsHLSLResourceType(type)) continue; - RegisterBinding(VD, unresolvedRegisters, map, GetHLSLResourceClass(type), + RegisterConsistentBinding(VD, unresolvedRegisters, map, GetHLSLResourceClass(type), arraySize, Diags, autoBindingSpace); } @@ -1275,6 +1280,620 @@ static void GenerateConsistentBindings(DeclContext &Ctx, } } +enum class DxcHLSLNodeType : uint64_t { + Register, + CBuffer, + Function, + Enum, + Namespace, + Typedef, + Using, + Variable, + Annotation +}; + +struct DxcHLSLNode { + + std::string Name; // Local name (not including parent's name) + + DxcHLSLNodeType NodeType : 4; + uint64_t LocalId : 24; // For example if Enum, maps into Enums[LocalId] + uint64_t AnnotationStart : 20; + uint64_t FileNameId : 16; // Index into Sources; 65535 == None + + uint64_t ChildCount : 24; // Children start at next node. childCount includes + // recursive children + uint64_t ParentId : 24; + uint64_t SourceLineCount : 16; + + uint64_t SourceLineStart : 20; // U20_MAX = No source range + uint64_t SourceColumnStart : 17; + uint64_t SourceColumnEnd : 17; + uint64_t AnnotationCount : 10; +}; + +struct DxcEnumDesc { + uint32_t NodeId; + uint32_t ValueCount; + uint32_t ValueLocation; +}; + +struct DxcEnumValue { + std::string Name; + int64_t Value; +}; + +struct DxcHLSLFunction { + uint32_t NodeId; + uint32_t NumParameters : 31; + uint32_t HasReturn : 1; +}; + +struct DxcHLSLRegister { //Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus the Name (and uID replaced with NodeID) + + D3D_SHADER_INPUT_TYPE Type; // Type of resource (e.g. texture, cbuffer, etc.) + uint32_t BindPoint; // Starting bind point + uint32_t BindCount; // Number of contiguous bind points (for arrays) + + uint32_t uFlags; // Input binding flags + D3D_RESOURCE_RETURN_TYPE ReturnType; // Return type (if texture) + D3D_SRV_DIMENSION Dimension; // Dimension (if texture) + uint32_t NumSamples; // Number of samples (0 if not MS texture) + uint32_t Space; // Register space + uint32_t NodeId; +}; + +struct ReflectionData { + std::vector Nodes; //0 = Root node (global scope) + std::vector Sources; + std::unordered_map SourceToFileId; + std::vector Registers; + std::vector Functions; + std::vector Enums; + std::vector EnumValues; +}; + +static uint32_t PushNextNodeId(ReflectionData &Refl, const SourceManager &SM, + const LangOptions &LangOpts, + const std::string &UnqualifiedName, Decl *Decl, + DxcHLSLNodeType Type, uint32_t ParentNodeId, + uint32_t LocalId) { + + assert(Refl.Nodes.size() < (uint32_t)(1 << 24) && "Nodes overflow"); + assert(LocalId < (uint32_t)(1 << 24) && "LocalId overflow"); + + uint32_t nodeId = Refl.Nodes.size(); + + uint32_t annotationStart = 0; // TODO: + uint32_t annotationCount = 0; // TODO: + + uint32_t sourceLineCount = 0; + uint32_t sourceLineStart = (1 << 20) - 1; + uint32_t sourceColumnStart = 0; + uint32_t sourceColumnEnd = 0; + + uint16_t fileNameId = (uint16_t)-1; + + SourceRange range = Decl->getSourceRange(); + SourceLocation start = range.getBegin(); + SourceLocation end = range.getEnd(); + + if (start.isValid() && end.isValid()) { + + PresumedLoc presumed = SM.getPresumedLoc(start); + + SourceLocation realEnd = SM.getFileLoc(end); + SourceLocation endOfToken = + Lexer::getLocForEndOfToken(realEnd, 0, SM, LangOpts); + PresumedLoc presumedEnd = SM.getPresumedLoc(endOfToken); + + if (presumed.isValid() && presumedEnd.isValid()) { + + uint32_t startLine = presumed.getLine(); + uint32_t startCol = presumed.getColumn(); + uint32_t endLine = presumedEnd.getLine(); + uint32_t endCol = presumedEnd.getColumn(); + + std::string fileName = presumed.getFilename(); + + assert(fileName == presumedEnd.getFilename() && + "End and start are not in the same file"); + + auto it = Refl.SourceToFileId.find(fileName); + uint32_t i; + + if (it == Refl.SourceToFileId.end()) { + i = (uint32_t)Refl.Sources.size(); + Refl.Sources.push_back(fileName); + Refl.SourceToFileId[fileName] = i; + } + + else { + i = it->second; + } + + assert(i < 65535 && "Source file count is limited to 16-bit"); + assert((endLine - startLine) < 65535 && + "Source line count is limited to 16-bit"); + assert(startLine < 1048576 && "Source line start is limited to 20-bit"); + assert(startCol < 131072 && "Column start is limited to 17-bit"); + assert(endCol < 131072 && "Column end is limited to 17-bit"); + + sourceLineCount = endLine - startLine + 1; + sourceLineStart = startLine; + sourceColumnStart = startCol; + sourceColumnEnd = endCol; + fileNameId = (uint16_t)i; + } + } + + Refl.Nodes.push_back({UnqualifiedName, Type, LocalId, annotationStart, + fileNameId, 0, ParentNodeId, sourceLineCount, + sourceLineStart, sourceColumnStart, sourceColumnEnd, + annotationCount}); + + uint32_t parentParent = ParentNodeId; + + while (parentParent != 0) { + DxcHLSLNode &parent = Refl.Nodes[parentParent]; + ++parent.ChildCount; + parentParent = parent.ParentId; + } + + ++Refl.Nodes[0].ChildCount; + + return nodeId; +} + +struct DxcRegisterTypeInfo { + D3D_SHADER_INPUT_TYPE RegisterType; + D3D_SHADER_INPUT_FLAGS RegisterFlags; + D3D_SRV_DIMENSION TextureDimension; + D3D_RESOURCE_RETURN_TYPE TextureValue; + uint32_t SampleCount; +}; + +class PrintfStream : public llvm::raw_ostream { +public: + PrintfStream() { SetUnbuffered(); } + +private: + void write_impl(const char *Ptr, size_t Size) override { + printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly + } + + uint64_t current_pos() const override { return 0; } +}; + +static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, + std::string TypeName, + bool IsWrite, + const CXXRecordDecl *RecordDecl) { + + DxcRegisterTypeInfo type = {}; + type.RegisterType = IsWrite ? D3D_SIT_UAV_RWTYPED : D3D_SIT_TEXTURE; + type.SampleCount = (uint32_t)-1; + + //Parse return type and dimensions + + const ClassTemplateSpecializationDecl *textureTemplate = + dyn_cast(RecordDecl); + + assert(textureTemplate && "Expected texture template"); + + const ArrayRef& textureParams = textureTemplate->getTemplateArgs().asArray(); + + assert(textureParams.size() == 1 && !textureParams[0].getAsType().isNull() && + "Expected template args"); + + QualType valueType = textureParams[0].getAsType(); + QualType desugared = valueType.getDesugaredType(ASTCtx); + + const RecordType *RT = desugared->getAs(); + assert(RT && "Expected record type"); + + const CXXRecordDecl *RD = dyn_cast(RT->getDecl()); + assert(RT && "Expected record decl"); + + const ClassTemplateSpecializationDecl *vectorType = + dyn_cast(RD); + + assert(vectorType && + "Expected vector type as template inside of texture template"); + + const ArrayRef &vectorParams = + vectorType->getTemplateArgs().asArray(); + + assert(vectorParams.size() == 2 && !vectorParams[0].getAsType().isNull() && + vectorParams[1].getKind() == TemplateArgument::Integral && + "Expected vector to be vector"); + + valueType = vectorParams[0].getAsType(); + desugared = valueType.getDesugaredType(ASTCtx); + + if (desugared->isFloatingType()) { + type.TextureValue = desugared->isSpecificBuiltinType(BuiltinType::Double) + ? D3D_RETURN_TYPE_DOUBLE + : D3D_RETURN_TYPE_FLOAT; + } else if (desugared->isIntegerType()) { + const auto &semantics = ASTCtx.getTypeInfo(desugared); + if (semantics.Width == 64) { + type.TextureValue = D3D_RETURN_TYPE_MIXED; + } else { + type.TextureValue = desugared->isUnsignedIntegerType() + ? D3D_RETURN_TYPE_UINT + : D3D_RETURN_TYPE_SINT; + } + } + + else { + type.TextureValue = D3D_RETURN_TYPE_MIXED; + } + + switch (vectorParams[1].getAsIntegral().getZExtValue()) { + case 2: + type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENT_0; + break; + case 3: + type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENT_1; + break; + case 4: + type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENTS; + break; + } + + //Parse type + + if (TypeName == "Buffer") { + type.TextureDimension = D3D_SRV_DIMENSION_BUFFER; + return type; + } + + bool isFeedback = false; + + if (TypeName.size() > 8 && TypeName.substr(0, 8) == "Feedback") { + isFeedback = true; + TypeName = TypeName.substr(8); + type.RegisterType = D3D_SIT_UAV_FEEDBACKTEXTURE; + } + + bool isArray = false; + + if (TypeName.size() > 5 && TypeName.substr(TypeName.size() - 5) == "Array") { + isArray = true; + TypeName = TypeName.substr(0, TypeName.size() - 5); + } + + if (TypeName == "Texture2D") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2D; + + else if (TypeName == "TextureCube") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURECUBE; + + else if (TypeName == "Texture3D") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE3D; + + else if (TypeName == "Texture1D") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE1D; + + else if (TypeName == "Texture2DMS") { + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2DMS; + type.SampleCount = 0; + } + + if (isArray) //Arrays are always 1 behind the regular type + type.TextureDimension = (D3D_SRV_DIMENSION)(type.TextureDimension + 1); + + return type; +} + +static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, + QualType Type) { + + QualType realType = Type.getDesugaredType(ASTCtx); + const RecordType *RT = realType->getAs(); + assert(RT && "GetRegisterTypeInfo() type is not a RecordType"); + + const CXXRecordDecl *recordDecl = RT->getAsCXXRecordDecl(); + assert(recordDecl && "GetRegisterTypeInfo() type is not a CXXRecordDecl"); + + std::string typeName = recordDecl->getNameAsString(); + + if (typeName.size() >= 17 && + typeName.substr(0, 17) == "RasterizerOrdered") { + typeName = typeName.substr(17); + } + + if (typeName == "SamplerState" || typeName == "SamplerComparisonState") { + return {D3D_SIT_SAMPLER, typeName == "SamplerComparisonState" + ? D3D_SIF_COMPARISON_SAMPLER + : (D3D_SHADER_INPUT_FLAGS)0}; + } + + DxcRegisterTypeInfo info = {}; + + if (const ClassTemplateSpecializationDecl *spec = + dyn_cast(recordDecl)) { + + const ArrayRef &array = + spec->getTemplateArgs().asArray(); + + if (array.size() == 1) + info.SampleCount = (uint32_t) (ASTCtx.getTypeSize(array[0].getAsType()) / 8); + } + + if (typeName == "AppendStructuredBuffer") { + info.RegisterType = D3D_SIT_UAV_APPEND_STRUCTURED; + return info; + } + + if (typeName == "ConsumeStructuredBuffer") { + info.RegisterType = D3D_SIT_UAV_CONSUME_STRUCTURED; + return info; + } + + if (typeName == "RaytracingAccelerationStructure") { + info.RegisterType = D3D_SIT_RTACCELERATIONSTRUCTURE; + info.SampleCount = (uint32_t)-1; + return info; + } + + if (typeName == "TextureBuffer") { + info.RegisterType = D3D_SIT_TBUFFER; + return info; + } + + if (typeName == "ConstantBuffer") { + info.RegisterType = D3D_SIT_CBUFFER; + return info; + } + + bool isWrite = + typeName.size() > 2 && typeName[0] == 'R' && typeName[1] == 'W'; + + if (isWrite) + typeName = typeName.substr(2); + + if (typeName == "StructuredBuffer") { + info.RegisterType = + isWrite ? D3D_SIT_UAV_RWSTRUCTURED : D3D_SIT_STRUCTURED; + return info; + } + + if (typeName == "ByteAddressBuffer") { + info.RegisterType = + isWrite ? D3D_SIT_UAV_RWBYTEADDRESS : D3D_SIT_BYTEADDRESS; + return info; + } + + return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); +} + +static void FillReflectionRegisterAt(const DeclContext &Ctx, ASTContext &ASTCtx, + const SourceManager &SM, + DiagnosticsEngine &Diag, QualType Type, + uint32_t ArraySize, ValueDecl *ValDesc, + ReflectionData &Refl, + uint32_t AutoBindingSpace, + uint32_t ParentNodeId) { + + ArrayRef UA = ValDesc->getUnusualAnnotations(); + + hlsl::RegisterAssignment *reg = nullptr; + + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { + + if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) + continue; + + reg = cast(*It); + } + + assert(reg && "Found a register missing a RegisterAssignment, even though " + "GenerateConsistentBindings should have already generated it"); + + DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, + DxcHLSLNodeType::Register, ParentNodeId, (uint32_t)Refl.Registers.size()); + + DxcHLSLRegister regD3D12 = { + + inputType.RegisterType, + reg->RegisterNumber, + ArraySize, + (uint32_t)inputType.RegisterFlags, + inputType.TextureValue, + inputType.TextureDimension, + inputType.SampleCount, + reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() + : AutoBindingSpace, + nodeId}; + + Refl.Registers.push_back(regD3D12); +} + +enum InclusionFlag { + InclusionFlag_Default = 0, //Includes cbuffer and registers + InclusionFlag_Functions = 1 << 0, + InclusionFlag_Namespaces = 1 << 1, + InclusionFlag_UserTypes = 1 << 2, //Include user types (struct, enum, typedef, etc.) + InclusionFlag_FunctionInternals = 1 << 3, //Variables, structs, functions defined in functions + InclusionFlag_Variables = 1 << 4, //Variables not included in $Global or cbuffers + InclusionFlag_Annotations = 1 << 5, //Annotations e.g. [[myAnnotation]] for additional reflection + InclusionFlag_All = (1 << 6) - 1 +}; + +static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, + DiagnosticsEngine &Diags, + const SourceManager &SM, + ReflectionData &Refl, + uint32_t AutoBindingSpace, + uint32_t Depth, + InclusionFlag InclusionFlags, + uint32_t ParentNodeId) { + + PrintfStream pfStream; + + PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); + + printingPolicy.SuppressInitializers = true; + printingPolicy.AnonymousTagLocations = false; + printingPolicy.TerseOutput = + true; // No inheritance list, trailing semicolons, etc. + printingPolicy.PolishForDeclaration = true; // Makes it print as a decl + printingPolicy.SuppressSpecifiers = false; // Prints e.g. "static" or "inline" + printingPolicy.SuppressScope = true; + + // Traverse AST to grab reflection data + + //TODO: Niels, Annotations, sources, scopes (if/switch/for/empty scope), nodes for tooling, + // flags for determining how heavy reflection should be (e.g. -reflect_hlsl = -reflect_hlsl_registers -reflect_hlsl_cbuffer -reflect_ + + for (Decl *it : Ctx.decls()) { + + SourceLocation Loc = it->getLocation(); + if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) + continue; + + if (HLSLBufferDecl *CBuffer = dyn_cast(it)) { + CBuffer->print(pfStream, printingPolicy); + } + + else if (FunctionDecl *Func = dyn_cast(it)) { + + if (!(InclusionFlags & InclusionFlag_Functions)) + continue; + + //TODO: Skip declaration, if full function is already declared, + // Otherwise take ownership of the previously declared one + + Func->print(pfStream, printingPolicy); + + const FunctionDecl *Definition = nullptr; + + //if (Func->hasBody(Definition)) + // RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, + // AutoBindingSpace, Depth + 1, InclusionFlags, nodeId); + } + + else if (FieldDecl *Field = dyn_cast(it)) { + + if (!(InclusionFlags & InclusionFlag_UserTypes)) + continue; + + Field->print(pfStream, printingPolicy); + } + + else if (TypedefDecl *Typedef = dyn_cast(it)) { + + if (!(InclusionFlags & InclusionFlag_UserTypes)) + continue; + + Typedef->print(pfStream, printingPolicy); + } + + else if (TypeAliasDecl *TypeAlias = dyn_cast(it)) { + + if (!(InclusionFlags & InclusionFlag_UserTypes)) + continue; + + TypeAlias->print(pfStream, printingPolicy); + } + + else if (EnumDecl *Enum = dyn_cast(it)) { + + if (!(InclusionFlags & InclusionFlag_UserTypes)) + continue; + + uint32_t enumStart = (uint32_t)Refl.EnumValues.size(); + + for (EnumConstantDecl *EnumValue : Enum->enumerators()) + Refl.EnumValues.push_back({EnumValue->getName(), + EnumValue->getInitVal().getSExtValue()}); + + assert(Refl.EnumValues.size() < (uint32_t)(1 << 30) && "Enum values overflow"); + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), Enum->getName(), Enum, + DxcHLSLNodeType::Enum, ParentNodeId, (uint32_t)Refl.Enums.size()); + + Refl.Enums.push_back( + {nodeId, (uint32_t)(Refl.EnumValues.size() - enumStart), enumStart}); + } + + else if (ValueDecl *ValDecl = dyn_cast(it)) { + + //TODO: Handle values + + ValDecl->print(pfStream); + + uint32_t arraySize = 1; + QualType type = ValDecl->getType(); + + if (const ConstantArrayType *arr = + dyn_cast(ValDecl->getType())) { + arraySize = arr->getSize().getZExtValue(); + type = arr->getElementType(); + } + + if (!IsHLSLResourceType(type)) + continue; + + ValDecl->print(pfStream, printingPolicy); + + if (Depth != 0) //TODO: Add for reflection even though it might not be important + continue; + + FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, ValDecl, + Refl, AutoBindingSpace, ParentNodeId); + } + + else if (RecordDecl *RecDecl = dyn_cast(it)) { + + if (!(InclusionFlags & InclusionFlag_UserTypes)) + continue; + + RecDecl->print(pfStream, printingPolicy); + /*RecursiveReflectHLSL(*RecDecl, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, InclusionFlags, nodeId);*/ + } + + else if (NamespaceDecl *Namespace = dyn_cast(it)) { + + if (!(InclusionFlags & InclusionFlag_Namespaces)) + continue; + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), Namespace->getName(), Namespace, + DxcHLSLNodeType::Namespace, ParentNodeId, 0); + + RecursiveReflectHLSL(*Namespace, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, InclusionFlags, nodeId); + } + } +} + +static void ReflectHLSL(ASTHelper &astHelper, ReflectionData& Refl, + uint32_t AutoBindingSpace) { + + TranslationUnitDecl &Ctx = *astHelper.tu; + DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); + const SourceManager &SM = astHelper.compiler.getSourceManager(); + + Refl.Nodes.push_back({ + "", + DxcHLSLNodeType::Namespace, + 0, + 0, + 0xFFFF + }); + + RecursiveReflectHLSL(Ctx, astHelper.compiler.getASTContext(), Diags, SM, Refl, + AutoBindingSpace, 0, InclusionFlag_All, 0); +} + static void GlobalVariableAsExternByDefault(DeclContext &Ctx) { for (auto it = Ctx.decls_begin(); it != Ctx.decls_end();) { auto cur = it++; @@ -1292,6 +1911,34 @@ static void GlobalVariableAsExternByDefault(DeclContext &Ctx) { } } +char RegisterGetSpaceChar(const DxcHLSLRegister ®) { + + switch (reg.Type) { + + case D3D_SIT_UAV_RWTYPED: + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_RWBYTEADDRESS: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: + case D3D_SIT_UAV_FEEDBACKTEXTURE: + return 'u'; + + case D3D_SIT_CBUFFER: + return 'b'; + + case D3D_SIT_SAMPLER: + return 's'; + + default: + return 't'; + } +} + +std::string RegisterGetArraySize(uint32_t count) { + return count > 1 ? "[" + std::to_string(count) + "]" : ""; +} + static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, ASTUnit::RemappedFile *pRemap, hlsl::options::DxcOpts &opts, @@ -1308,10 +1955,36 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, TranslationUnitDecl *tu = astHelper.tu; - if (opts.RWOpt.ConsistentBindings) { + if (opts.RWOpt.ConsistentBindings || opts.RWOpt.ReflectHLSL) { GenerateConsistentBindings(*tu, opts.AutoBindingSpace); } + if (opts.RWOpt.ReflectHLSL) { + ReflectionData Refl; + ReflectHLSL(astHelper, Refl, opts.AutoBindingSpace); + + for (DxcEnumDesc en : Refl.Enums) { + printf("Enum: %s (%u values starting at %u)\n", Refl.Nodes[en.NodeId].Name.c_str(), + en.ValueCount, en.ValueLocation); + + for (uint32_t i = 0; i < en.ValueCount; ++i) + printf("%u %s = %" PRIi64 "\n", i, + Refl.EnumValues[en.ValueLocation + i].Name.c_str(), + Refl.EnumValues[en.ValueLocation + i].Value); + } + + for (DxcHLSLRegister reg : Refl.Registers) { + printf("%s%s : register(%c%u, space%u);\n", + Refl.Nodes[reg.NodeId].Name.c_str(), + RegisterGetArraySize(reg.BindCount).c_str(), + RegisterGetSpaceChar(reg), + reg.BindPoint, + reg.Space); + } + + printf("%p\n", &Refl); + } + if (opts.RWOpt.SkipStatic && opts.RWOpt.SkipFunctionBody) { // Remove static functions and globals. RemoveStaticDecls(*tu); @@ -1330,7 +2003,7 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, opts.RWOpt.RemoveUnusedFunctions, w); if (FAILED(hr)) return hr; - } else if (!opts.RWOpt.ConsistentBindings) { + } else if (!opts.RWOpt.ConsistentBindings && !opts.RWOpt.ReflectHLSL) { o << "// Rewrite unchanged result:\n"; } From f9b00905c0647a672fc0ba0856112da6bb39d699 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 2 Aug 2025 23:17:47 +0200 Subject: [PATCH 006/126] Enums now have a type and started thinking about function parameters, though that one is a bit tricky. Functions are now registered. Up next: CBuffer & annotations. --- include/dxc/dxctools.h | 10 + .../clang/tools/libclang/dxcrewriteunused.cpp | 193 +++++++++++++++--- 2 files changed, 175 insertions(+), 28 deletions(-) diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index b721611b29..7394d1b094 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -92,9 +92,19 @@ struct D3D12_HLSL_FUNCTION_DESC { // subroutine }; +enum D3D12_HLSL_ENUM_TYPE { + D3D12_HLSL_ENUM_TYPE_UINT, + D3D12_HLSL_ENUM_TYPE_INT, + D3D12_HLSL_ENUM_TYPE_UINT64_T, + D3D12_HLSL_ENUM_TYPE_INT64_T, + D3D12_HLSL_ENUM_TYPE_UINT16_T, + D3D12_HLSL_ENUM_TYPE_INT16_T +}; + struct D3D12_HLSL_ENUM_DESC { LPCSTR Name; UINT ValueCount; + D3D12_HLSL_ENUM_TYPE Type; }; struct D3D12_HLSL_ENUM_VALUE { diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 740ee16b57..3a79c3597d 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1285,11 +1285,12 @@ enum class DxcHLSLNodeType : uint64_t { CBuffer, Function, Enum, + EnumValue, Namespace, Typedef, Using, Variable, - Annotation + Parameter }; struct DxcHLSLNode { @@ -1314,19 +1315,32 @@ struct DxcHLSLNode { struct DxcEnumDesc { uint32_t NodeId; - uint32_t ValueCount; - uint32_t ValueLocation; + D3D12_HLSL_ENUM_TYPE Type; }; struct DxcEnumValue { - std::string Name; int64_t Value; + uint32_t NodeId; +}; + +struct DxcHLSLParameter { //Mirrors D3D12_PARAMETER_DESC (ex. First(In/Out)(Register/Component)), but with std::string and NodeId + std::string SemanticName; + D3D_SHADER_VARIABLE_TYPE Type; // Element type. + D3D_SHADER_VARIABLE_CLASS Class; // Scalar/Vector/Matrix. + uint32_t Rows; // Rows are for matrix parameters. + uint32_t Columns; // Components or Columns in matrix. + D3D_INTERPOLATION_MODE InterpolationMode; // Interpolation mode. + D3D_PARAMETER_FLAGS Flags; // Parameter modifiers. + uint32_t NodeId; + + //TODO: Array info }; struct DxcHLSLFunction { uint32_t NodeId; - uint32_t NumParameters : 31; + uint32_t NumParameters : 30; uint32_t HasReturn : 1; + uint32_t HasDefinition : 1; }; struct DxcHLSLRegister { //Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus the Name (and uID replaced with NodeID) @@ -1351,6 +1365,7 @@ struct ReflectionData { std::vector Functions; std::vector Enums; std::vector EnumValues; + std::vector Parameters; }; static uint32_t PushNextNodeId(ReflectionData &Refl, const SourceManager &SM, @@ -1714,6 +1729,55 @@ static void FillReflectionRegisterAt(const DeclContext &Ctx, ASTContext &ASTCtx, Refl.Registers.push_back(regD3D12); } +/* +static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, + ReflectionData &Refl, const SourceManager &SM, + uint32_t ParentNodeId) { + + PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); + + QualType desugared = Type.getDesugaredType(ASTCtx); + + PrintfStream str; + desugared.print(str, printingPolicy); + + if (Decl) + Decl->print(str); + + //Generate parameter + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), + Decl && dyn_cast(Decl) ? dyn_cast(Decl)->getName() + : "", + Decl, DxcHLSLNodeType::Parameter, ParentNodeId, + (uint32_t)Refl.Parameters.size()); + + std::string semanticName; + + if (NamedDecl *ValDesc = dyn_cast(Decl)) { + + ArrayRef UA = ValDesc->getUnusualAnnotations(); + + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { + + if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_SemanticDecl) + continue; + + semanticName = cast(*It)->SemanticName; + } + } + + DxcHLSLParameter parameter{std::move(semanticName)}; + + type, clss, rows, columns, interpolationMode, flags; + parameter.NodeId = nodeId; + + Refl.Parameters.push_back(parameter); + + //It's a struct, add parameters recursively +}*/ + enum InclusionFlag { InclusionFlag_Default = 0, //Includes cbuffer and registers InclusionFlag_Functions = 1 << 0, @@ -1766,16 +1830,34 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(InclusionFlags & InclusionFlag_Functions)) continue; - //TODO: Skip declaration, if full function is already declared, - // Otherwise take ownership of the previously declared one + const FunctionDecl *Definition = nullptr; - Func->print(pfStream, printingPolicy); + uint32_t nodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), Func->getName(), Func, + DxcHLSLNodeType::Function, ParentNodeId, + (uint32_t)Refl.Functions.size()); - const FunctionDecl *Definition = nullptr; + bool hasDefinition = Func->hasBody(Definition); + DxcHLSLFunction func = {nodeId, Func->getNumParams(), + !Func->getReturnType().getTypePtr()->isVoidType(), + hasDefinition}; + + /* + for (uint32_t i = 0; i < func.NumParameters; ++i) + AddFunctionParameters(ASTCtx, Func->getParamDecl(i)->getType(), + Func->getParamDecl(i), Refl, SM, nodeId); + + if (func.HasReturn) + AddFunctionParameters(ASTCtx, Func->getReturnType(), nullptr, Refl, SM, + nodeId);*/ - //if (Func->hasBody(Definition)) - // RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, - // AutoBindingSpace, Depth + 1, InclusionFlags, nodeId); + Refl.Functions.push_back(std::move(func)); + + if (hasDefinition && (InclusionFlags & InclusionFlag_FunctionInternals)) { + RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, InclusionFlags, + nodeId); + } } else if (FieldDecl *Field = dyn_cast(it)) { @@ -1807,20 +1889,52 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(InclusionFlags & InclusionFlag_UserTypes)) continue; - uint32_t enumStart = (uint32_t)Refl.EnumValues.size(); - - for (EnumConstantDecl *EnumValue : Enum->enumerators()) - Refl.EnumValues.push_back({EnumValue->getName(), - EnumValue->getInitVal().getSExtValue()}); - - assert(Refl.EnumValues.size() < (uint32_t)(1 << 30) && "Enum values overflow"); - uint32_t nodeId = PushNextNodeId( Refl, SM, ASTCtx.getLangOpts(), Enum->getName(), Enum, DxcHLSLNodeType::Enum, ParentNodeId, (uint32_t)Refl.Enums.size()); - Refl.Enums.push_back( - {nodeId, (uint32_t)(Refl.EnumValues.size() - enumStart), enumStart}); + for (EnumConstantDecl *EnumValue : Enum->enumerators()) { + + uint32_t childNodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), EnumValue->getName(), + EnumValue, DxcHLSLNodeType::EnumValue, nodeId, + (uint32_t)Refl.EnumValues.size()); + + Refl.EnumValues.push_back( + {EnumValue->getInitVal().getSExtValue(), childNodeId}); + } + + assert(Refl.EnumValues.size() < (uint32_t)(1 << 30) && + "Enum values overflow"); + + QualType enumType = Enum->getIntegerType(); + QualType desugared = enumType.getDesugaredType(ASTCtx); + const auto &semantics = ASTCtx.getTypeInfo(desugared); + + D3D12_HLSL_ENUM_TYPE type; + + switch (semantics.Width) { + + default: + case 32: + type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT + : D3D12_HLSL_ENUM_TYPE_INT; + break; + + case 16: + type = desugared->isUnsignedIntegerType() + ? D3D12_HLSL_ENUM_TYPE_UINT16_T + : D3D12_HLSL_ENUM_TYPE_INT16_T; + break; + + case 64: + type = desugared->isUnsignedIntegerType() + ? D3D12_HLSL_ENUM_TYPE_UINT64_T + : D3D12_HLSL_ENUM_TYPE_INT64_T; + break; + } + + Refl.Enums.push_back({nodeId, type}); } else if (ValueDecl *ValDecl = dyn_cast(it)) { @@ -1939,6 +2053,15 @@ std::string RegisterGetArraySize(uint32_t count) { return count > 1 ? "[" + std::to_string(count) + "]" : ""; } +std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { + + const char *arr[] = { + "uint", "int", "uint64_t", "int64_t", "uint16_t", "int16_t", + }; + + return arr[type]; +} + static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, ASTUnit::RemappedFile *pRemap, hlsl::options::DxcOpts &opts, @@ -1964,13 +2087,19 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, ReflectHLSL(astHelper, Refl, opts.AutoBindingSpace); for (DxcEnumDesc en : Refl.Enums) { - printf("Enum: %s (%u values starting at %u)\n", Refl.Nodes[en.NodeId].Name.c_str(), - en.ValueCount, en.ValueLocation); - for (uint32_t i = 0; i < en.ValueCount; ++i) - printf("%u %s = %" PRIi64 "\n", i, - Refl.EnumValues[en.ValueLocation + i].Name.c_str(), - Refl.EnumValues[en.ValueLocation + i].Value); + printf("Enum: %s (: %s)\n", Refl.Nodes[en.NodeId].Name.c_str(), + EnumTypeToString(en.Type).c_str()); + + DxcHLSLNode node = Refl.Nodes[en.NodeId]; + + for (uint32_t i = 0; i < node.ChildCount; ++i) { + + DxcHLSLNode child = Refl.Nodes[en.NodeId + 1 + i]; + + printf("%u %s = %" PRIi64 "\n", i, child.Name.c_str(), + Refl.EnumValues[child.LocalId].Value); + } } for (DxcHLSLRegister reg : Refl.Registers) { @@ -1982,6 +2111,14 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, reg.Space); } + for (DxcHLSLFunction func : Refl.Functions) { + printf("%s (return: %s, hasDefinition: %s, numParams: %u)\n", + Refl.Nodes[func.NodeId].Name.c_str(), + func.HasReturn ? "true" : "false", + func.HasDefinition ? "true" : "false", + func.NumParameters); + } + printf("%p\n", &Refl); } From 75b63ca578d894eb81faf190be012d4362681ec1 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 3 Aug 2025 19:08:17 +0200 Subject: [PATCH 007/126] Added a language option for 'PreserveUnknownAnnotations', this is a temporary hack, required because unknown annotations [[custom::syntax("test")]] emit a warning and don't make it to the AST. With this enabled, it will turn these annotations into a clang annotation and preserves the entire syntax as intended for further parsing. Usage for this can vary from reflection info (example: providing a static sampler for the engine to create) to the pre-processor guiding how to compile the final binary (for example an alternative to [shader("vertex")] with oxc::stage to allow compiling it as a standalone entrypoint). These annotations eventually end up into the reflection data object for IDxcHLSLReflection and they are attached per node; each node has an annotation start and count. Also disabled temporary debug prints in RecursiveReflectHLSL. Added some temporary debug utilities to recursively print nodes and their annotations. --- tools/clang/include/clang/Basic/LangOptions.h | 1 + tools/clang/lib/Sema/SemaDeclAttr.cpp | 52 +++++++++++ .../clang/tools/libclang/dxcrewriteunused.cpp | 91 ++++++++++++++----- 3 files changed, 123 insertions(+), 21 deletions(-) diff --git a/tools/clang/include/clang/Basic/LangOptions.h b/tools/clang/include/clang/Basic/LangOptions.h index 433b767c8d..bb8a895e22 100644 --- a/tools/clang/include/clang/Basic/LangOptions.h +++ b/tools/clang/include/clang/Basic/LangOptions.h @@ -164,6 +164,7 @@ class LangOptions : public LangOptionsBase { bool EnablePayloadAccessQualifiers = false; bool DumpImplicitTopLevelDecls = true; bool ExportShadersOnly = false; + bool PreserveUnknownAnnotations = false; hlsl::DXIL::DefaultLinkage DefaultLinkage = hlsl::DXIL::DefaultLinkage::Default; /// Whether use row major as default matrix major. diff --git a/tools/clang/lib/Sema/SemaDeclAttr.cpp b/tools/clang/lib/Sema/SemaDeclAttr.cpp index 085874a0ed..763f811391 100644 --- a/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -4585,6 +4585,58 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, // though they were unknown attributes. if (Attr.getKind() == AttributeList::UnknownAttribute || !Attr.existsInTarget(S.Context.getTargetInfo().getTriple())) { + + //HLSL change, language option to maintain unknown annotations. + //This is extremely useful for extending the language for providing extra reflection info. + //These annotations are accessible through IDxcHLSLReflection. + + const LangOptions &LangOpts = S.Context.getLangOpts(); + + if (LangOpts.HLSL && LangOpts.PreserveUnknownAnnotations) { + + //In the case of oxc::stage("compute") clang only maintains oxc::stage. + //We get around this by instantiating a lexer and finding the end of the annotation (]]). + //We don't do any cleanup and pass the inside of [[]] as is, so any external parsing can be done on it. + + SourceRange AttrRange = Attr.getRange(); + + const SourceManager &SM = S.Context.getSourceManager(); + const LangOptions &LO = S.Context.getLangOpts(); + FileID FID = SM.getFileID(Attr.getLoc()); + StringRef Buffer = SM.getBufferData(FID); + const char *AttrData = SM.getCharacterData(AttrRange.getBegin()); + + SourceLocation BeginLoc = AttrRange.getBegin(); + SourceLocation EndLoc = AttrRange.getEnd(); + + Lexer Lex(SM.getLocForStartOfFile(FID), LangOpts, Buffer.begin(), + AttrData, Buffer.end()); + + Token Tok; + while (!Lex.LexFromRawLexer(Tok)) { //Search until ]] + + if (!Tok.is(tok::r_square)) + continue; + + Token Next; + if (Lex.LexFromRawLexer(Next)) + break; + + if (!Next.is(tok::r_square)) + continue; + + EndLoc = Tok.getLocation(); + break; + } + + StringRef FullAttrSpelling = Lexer::getSourceText( + CharSourceRange::getCharRange(BeginLoc, EndLoc), SM, LO); + + D->addAttr(AnnotateAttr::CreateImplicit(S.Context, FullAttrSpelling, + Attr.getLoc())); + return; + } + S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ? diag::warn_unhandled_ms_attribute_ignored : diag::warn_unknown_attribute_ignored) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 3a79c3597d..1fb3caa5f9 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -544,6 +544,7 @@ void SetupCompilerCommon(CompilerInstance &compiler, compiler.getDiagnostics().setWarningsAsErrors(true); compiler.getDiagnostics().setIgnoreAllWarnings(!opts.OutputWarnings); compiler.getLangOpts().HLSLVersion = opts.HLSLVersion; + compiler.getLangOpts().PreserveUnknownAnnotations = opts.RWOpt.ReflectHLSL; compiler.getLangOpts().UseMinPrecision = !opts.Enable16BitTypes; compiler.getLangOpts().EnableDX9CompatMode = opts.EnableDX9CompatMode; compiler.getLangOpts().EnableFXCCompatMode = opts.EnableFXCCompatMode; @@ -1366,6 +1367,19 @@ struct ReflectionData { std::vector Enums; std::vector EnumValues; std::vector Parameters; + std::vector Annotations; +}; + +class PrintfStream : public llvm::raw_ostream { +public: + PrintfStream() { SetUnbuffered(); } + +private: + void write_impl(const char *Ptr, size_t Size) override { + printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly + } + + uint64_t current_pos() const override { return 0; } }; static uint32_t PushNextNodeId(ReflectionData &Refl, const SourceManager &SM, @@ -1379,8 +1393,23 @@ static uint32_t PushNextNodeId(ReflectionData &Refl, const SourceManager &SM, uint32_t nodeId = Refl.Nodes.size(); - uint32_t annotationStart = 0; // TODO: - uint32_t annotationCount = 0; // TODO: + uint32_t annotationStart = (uint32_t) Refl.Annotations.size(); + uint32_t annotationCount = 0; + + if (Decl) { + + PrintfStream pfStream; + + LangOptions dummy; + PrintingPolicy printingPolicy(dummy); + + for (const Attr *attr : Decl->attrs()) { + if (const AnnotateAttr *annotate = dyn_cast(attr)) { + Refl.Annotations.push_back(annotate->getAnnotation().str()); + ++annotationCount; + } + } + } uint32_t sourceLineCount = 0; uint32_t sourceLineStart = (1 << 20) - 1; @@ -1468,18 +1497,6 @@ struct DxcRegisterTypeInfo { uint32_t SampleCount; }; -class PrintfStream : public llvm::raw_ostream { -public: - PrintfStream() { SetUnbuffered(); } - -private: - void write_impl(const char *Ptr, size_t Size) override { - printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly - } - - uint64_t current_pos() const override { return 0; } -}; - static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, std::string TypeName, bool IsWrite, @@ -1822,7 +1839,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, continue; if (HLSLBufferDecl *CBuffer = dyn_cast(it)) { - CBuffer->print(pfStream, printingPolicy); + //CBuffer->print(pfStream, printingPolicy); } else if (FunctionDecl *Func = dyn_cast(it)) { @@ -1865,7 +1882,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(InclusionFlags & InclusionFlag_UserTypes)) continue; - Field->print(pfStream, printingPolicy); + //Field->print(pfStream, printingPolicy); } else if (TypedefDecl *Typedef = dyn_cast(it)) { @@ -1873,7 +1890,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(InclusionFlags & InclusionFlag_UserTypes)) continue; - Typedef->print(pfStream, printingPolicy); + // Typedef->print(pfStream, printingPolicy); } else if (TypeAliasDecl *TypeAlias = dyn_cast(it)) { @@ -1881,7 +1898,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(InclusionFlags & InclusionFlag_UserTypes)) continue; - TypeAlias->print(pfStream, printingPolicy); + // TypeAlias->print(pfStream, printingPolicy); } else if (EnumDecl *Enum = dyn_cast(it)) { @@ -1941,7 +1958,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, //TODO: Handle values - ValDecl->print(pfStream); + //ValDecl->print(pfStream); uint32_t arraySize = 1; QualType type = ValDecl->getType(); @@ -1955,7 +1972,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!IsHLSLResourceType(type)) continue; - ValDecl->print(pfStream, printingPolicy); + //ValDecl->print(pfStream, printingPolicy); if (Depth != 0) //TODO: Add for reflection even though it might not be important continue; @@ -1969,7 +1986,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(InclusionFlags & InclusionFlag_UserTypes)) continue; - RecDecl->print(pfStream, printingPolicy); + //RecDecl->print(pfStream, printingPolicy); /*RecursiveReflectHLSL(*RecDecl, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, InclusionFlags, nodeId);*/ } @@ -2062,6 +2079,36 @@ std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { return arr[type]; } +std::string NodeTypeToString(DxcHLSLNodeType type) { + + const char *arr[] = {"Register", "CBuffer", "Function", "Enum", + "EnumValue", "Namespace", "Typedef", "Using", + "Variable", "Parameter"}; + + return arr[(int)type]; +} + +uint32_t RecursePrint(const ReflectionData &Refl, uint32_t NodeId, + uint32_t Depth) { + + const DxcHLSLNode &node = Refl.Nodes[NodeId]; + + if (NodeId) { + + printf("%s%s %s\n", std::string(Depth - 1, '\t').c_str(), + NodeTypeToString(node.NodeType).c_str(), node.Name.c_str()); + + for (uint32_t i = 0; i < node.AnnotationCount; ++i) + printf("%s[[%s]]\n", std::string(Depth, '\t').c_str(), + Refl.Annotations[i].c_str()); + } + + for (uint32_t i = 0; i < node.ChildCount; ++i) + i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1); + + return node.ChildCount; +} + static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, ASTUnit::RemappedFile *pRemap, hlsl::options::DxcOpts &opts, @@ -2119,6 +2166,8 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, func.NumParameters); } + RecursePrint(Refl, 0, 0); + printf("%p\n", &Refl); } From 8af90b73c66b12a9563f69f63715797d89cfbaa6 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 3 Aug 2025 19:20:10 +0200 Subject: [PATCH 008/126] RecursiveReflectHLSL will temporarily flatten the descriptor array, TBD: provide more information to allow a full reflect. Will apply the same thing to consistent-bindings --- tools/clang/tools/libclang/dxcrewriteunused.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 1fb3caa5f9..1fba15327b 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1963,9 +1963,9 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, uint32_t arraySize = 1; QualType type = ValDecl->getType(); - if (const ConstantArrayType *arr = - dyn_cast(ValDecl->getType())) { - arraySize = arr->getSize().getZExtValue(); + while (const ConstantArrayType *arr = + dyn_cast(type)) { + arraySize *= arr->getSize().getZExtValue(); type = arr->getElementType(); } From a78fbcc01c0bccc363852d5ce9f37c97ff613906 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 3 Aug 2025 19:21:41 +0200 Subject: [PATCH 009/126] Now supporting multi dimensional register arrays for -consistent-bindings --- tools/clang/tools/libclang/dxcrewriteunused.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 1fba15327b..f77befbc2e 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1210,9 +1210,8 @@ static void GenerateConsistentBindings(DeclContext &Ctx, uint32_t arraySize = 1; QualType type = VD->getType(); - if (const ConstantArrayType *arr = - dyn_cast(VD->getType())) { - arraySize = arr->getSize().getZExtValue(); + while (const ConstantArrayType *arr = dyn_cast(type)) { + arraySize *= arr->getSize().getZExtValue(); type = arr->getElementType(); } From 7f421813a335a9740dd7b1d0357d333b5761c72c Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 3 Aug 2025 20:09:46 +0200 Subject: [PATCH 010/126] Renamed Dxc reflection structs to DxcHLSL to separate it. Now exposing array ids to handle register multi dimensional arrays if there is more than just 1 array dimension; aka reflection can now maintain full array info of a register (up to 8 like spirv). --- .../clang/tools/libclang/dxcrewriteunused.cpp | 166 ++++++++++++------ 1 file changed, 109 insertions(+), 57 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index f77befbc2e..d588c7a0c8 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1313,12 +1313,12 @@ struct DxcHLSLNode { uint64_t AnnotationCount : 10; }; -struct DxcEnumDesc { +struct DxcHLSLEnumDesc { uint32_t NodeId; D3D12_HLSL_ENUM_TYPE Type; }; -struct DxcEnumValue { +struct DxcHLSLEnumValue { int64_t Value; uint32_t NodeId; }; @@ -1343,18 +1343,32 @@ struct DxcHLSLFunction { uint32_t HasDefinition : 1; }; -struct DxcHLSLRegister { //Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus the Name (and uID replaced with NodeID) - - D3D_SHADER_INPUT_TYPE Type; // Type of resource (e.g. texture, cbuffer, etc.) - uint32_t BindPoint; // Starting bind point - uint32_t BindCount; // Number of contiguous bind points (for arrays) - - uint32_t uFlags; // Input binding flags - D3D_RESOURCE_RETURN_TYPE ReturnType; // Return type (if texture) - D3D_SRV_DIMENSION Dimension; // Dimension (if texture) - uint32_t NumSamples; // Number of samples (0 if not MS texture) - uint32_t Space; // Register space - uint32_t NodeId; +struct DxcHLSLRegister { //Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus the Name (and uID replaced with NodeID) and added arrayIndex + + D3D_SHADER_INPUT_TYPE Type; // Type of resource (e.g. texture, cbuffer, etc.) + uint32_t BindPoint; // Starting bind point + uint32_t BindCount; // Number of contiguous bind points (for arrays) + + uint32_t uFlags; // Input binding flags + D3D_RESOURCE_RETURN_TYPE ReturnType; // Return type (if texture) + D3D_SRV_DIMENSION Dimension; // Dimension (if texture) + uint32_t NumSamples; // Number of samples (0 if not MS texture) + uint32_t Space; // Register space + uint32_t NodeId; + uint32_t ArrayId; // Only accessible if BindCount > 1 and the array is multi dimensional +}; + +struct DxcHLSLArray { + uint32_t ArrayElem : 4; // Array of up to 8 recursion levels deep (like spirv) + uint32_t ArrayStart : 28; // Index into ArraySizes with ArraySize +}; + +struct DxcRegisterTypeInfo { + D3D_SHADER_INPUT_TYPE RegisterType; + D3D_SHADER_INPUT_FLAGS RegisterFlags; + D3D_SRV_DIMENSION TextureDimension; + D3D_RESOURCE_RETURN_TYPE TextureValue; + uint32_t SampleCount; }; struct ReflectionData { @@ -1363,22 +1377,12 @@ struct ReflectionData { std::unordered_map SourceToFileId; std::vector Registers; std::vector Functions; - std::vector Enums; - std::vector EnumValues; + std::vector Enums; + std::vector EnumValues; std::vector Parameters; std::vector Annotations; -}; - -class PrintfStream : public llvm::raw_ostream { -public: - PrintfStream() { SetUnbuffered(); } - -private: - void write_impl(const char *Ptr, size_t Size) override { - printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly - } - - uint64_t current_pos() const override { return 0; } + std::vector Arrays; + std::vector ArraySizes; }; static uint32_t PushNextNodeId(ReflectionData &Refl, const SourceManager &SM, @@ -1396,14 +1400,9 @@ static uint32_t PushNextNodeId(ReflectionData &Refl, const SourceManager &SM, uint32_t annotationCount = 0; if (Decl) { - - PrintfStream pfStream; - - LangOptions dummy; - PrintingPolicy printingPolicy(dummy); - for (const Attr *attr : Decl->attrs()) { if (const AnnotateAttr *annotate = dyn_cast(attr)) { + assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); Refl.Annotations.push_back(annotate->getAnnotation().str()); ++annotationCount; } @@ -1488,14 +1487,6 @@ static uint32_t PushNextNodeId(ReflectionData &Refl, const SourceManager &SM, return nodeId; } -struct DxcRegisterTypeInfo { - D3D_SHADER_INPUT_TYPE RegisterType; - D3D_SHADER_INPUT_FLAGS RegisterFlags; - D3D_SRV_DIMENSION TextureDimension; - D3D_RESOURCE_RETURN_TYPE TextureValue; - uint32_t SampleCount; -}; - static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, std::string TypeName, bool IsWrite, @@ -1700,13 +1691,41 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); } -static void FillReflectionRegisterAt(const DeclContext &Ctx, ASTContext &ASTCtx, - const SourceManager &SM, - DiagnosticsEngine &Diag, QualType Type, - uint32_t ArraySize, ValueDecl *ValDesc, - ReflectionData &Refl, - uint32_t AutoBindingSpace, - uint32_t ParentNodeId) { +static uint32_t PushArray(ReflectionData &Refl, uint32_t ArraySizeFlat, + const std::vector &ArraySize) { + + if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) + return (uint32_t)-1; + + assert(Refl.Arrays.size() < (uint32_t)-1 && "Arrays would overflow"); + uint32_t arrayId = (uint32_t)Refl.Arrays.size(); + + uint32_t arrayCountStart = (uint32_t)Refl.ArraySizes.size(); + uint32_t numArrayElements = std::min((size_t)8, ArraySize.size()); + assert(Refl.ArraySizes.size() + numArrayElements < ((1 << 28) - 1) && + "Array elements would overflow"); + + for (uint32_t i = 0; i < ArraySize.size() && i < 8; ++i) { + + uint32_t arraySize = ArraySize[i]; + + // Flatten rest of array to at least keep consistent array elements + if (i == 7) + for (uint32_t j = i + 1; j < ArraySize.size(); ++j) + arraySize *= ArraySize[j]; + + Refl.ArraySizes.push_back(arraySize); + } + + Refl.Arrays.push_back({numArrayElements, arrayCountStart}); + return arrayId; +} + +static void FillReflectionRegisterAt( + const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, + DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, + ValueDecl *ValDesc, const std::vector &ArraySize, + ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId) { ArrayRef UA = ValDesc->getUnusualAnnotations(); @@ -1729,18 +1748,22 @@ static void FillReflectionRegisterAt(const DeclContext &Ctx, ASTContext &ASTCtx, Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, DxcHLSLNodeType::Register, ParentNodeId, (uint32_t)Refl.Registers.size()); + uint32_t arrayId = PushArray(Refl, ArraySizeFlat, ArraySize); + DxcHLSLRegister regD3D12 = { inputType.RegisterType, reg->RegisterNumber, - ArraySize, + ArraySizeFlat, (uint32_t)inputType.RegisterFlags, inputType.TextureValue, inputType.TextureDimension, inputType.SampleCount, reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() : AutoBindingSpace, - nodeId}; + nodeId, + arrayId + }; Refl.Registers.push_back(regD3D12); } @@ -1805,6 +1828,19 @@ enum InclusionFlag { InclusionFlag_All = (1 << 6) - 1 }; +class PrintfStream : public llvm::raw_ostream { +public: + PrintfStream() { SetUnbuffered(); } + +private: + void write_impl(const char *Ptr, size_t Size) override { + printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly + } + + uint64_t current_pos() const override { return 0; } +}; + + static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, @@ -1814,6 +1850,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, InclusionFlag InclusionFlags, uint32_t ParentNodeId) { + /* PrintfStream pfStream; PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); @@ -1824,7 +1861,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, true; // No inheritance list, trailing semicolons, etc. printingPolicy.PolishForDeclaration = true; // Makes it print as a decl printingPolicy.SuppressSpecifiers = false; // Prints e.g. "static" or "inline" - printingPolicy.SuppressScope = true; + printingPolicy.SuppressScope = true;*/ // Traverse AST to grab reflection data @@ -1961,9 +1998,12 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, uint32_t arraySize = 1; QualType type = ValDecl->getType(); + std::vector arrayElem; while (const ConstantArrayType *arr = dyn_cast(type)) { + uint32_t current = arr->getSize().getZExtValue(); + arrayElem.push_back(current); arraySize *= arr->getSize().getZExtValue(); type = arr->getElementType(); } @@ -1977,7 +2017,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, continue; FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, ValDecl, - Refl, AutoBindingSpace, ParentNodeId); + arrayElem, Refl, AutoBindingSpace, ParentNodeId); } else if (RecordDecl *RecDecl = dyn_cast(it)) { @@ -2065,8 +2105,20 @@ char RegisterGetSpaceChar(const DxcHLSLRegister ®) { } } -std::string RegisterGetArraySize(uint32_t count) { - return count > 1 ? "[" + std::to_string(count) + "]" : ""; +std::string RegisterGetArraySize(const ReflectionData &Refl, const DxcHLSLRegister ®) { + + if (reg.ArrayId != (uint32_t)-1) { + + DxcHLSLArray arr = Refl.Arrays[reg.ArrayId]; + std::string str; + + for (uint32_t i = 0; i < arr.ArrayElem; ++i) + str += "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart + i]) + "]"; + + return str; + } + + return reg.BindCount > 1 ? "[" + std::to_string(reg.BindCount) + "]" : ""; } std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { @@ -2132,7 +2184,7 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, ReflectionData Refl; ReflectHLSL(astHelper, Refl, opts.AutoBindingSpace); - for (DxcEnumDesc en : Refl.Enums) { + for (DxcHLSLEnumDesc en : Refl.Enums) { printf("Enum: %s (: %s)\n", Refl.Nodes[en.NodeId].Name.c_str(), EnumTypeToString(en.Type).c_str()); @@ -2151,7 +2203,7 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, for (DxcHLSLRegister reg : Refl.Registers) { printf("%s%s : register(%c%u, space%u);\n", Refl.Nodes[reg.NodeId].Name.c_str(), - RegisterGetArraySize(reg.BindCount).c_str(), + RegisterGetArraySize(Refl, reg).c_str(), RegisterGetSpaceChar(reg), reg.BindPoint, reg.Space); From 092532b53506b2ad21662aa09040adea7e070fb8 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 5 Aug 2025 21:30:22 +0200 Subject: [PATCH 011/126] Added multiple reflection settings to determine what the user wants to export (e.g. registers + cbuffer (basics), functions, namespaces, user-types, function-internals, variables) to keep the AST small if not more info is needed --- include/dxc/Support/HLSLOptions.h | 29 ++++--- include/dxc/Support/HLSLOptions.td | 14 +++- lib/DxcSupport/HLSLOptions.cpp | 14 +++- .../clang/tools/libclang/dxcrewriteunused.cpp | 81 +++++++++++++------ 4 files changed, 97 insertions(+), 41 deletions(-) diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index 08777e5426..ca5740caa6 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -102,18 +102,23 @@ class DxcDefines { }; struct RewriterOpts { - bool Unchanged = false; // OPT_rw_unchanged - bool ConsistentBindings = false; // OPT_rw_consistent_bindings - bool ReflectHLSL = false; // OPT_rw_reflect_hlsl - bool SkipFunctionBody = false; // OPT_rw_skip_function_body - bool SkipStatic = false; // OPT_rw_skip_static - bool GlobalExternByDefault = false; // OPT_rw_global_extern_by_default - bool KeepUserMacro = false; // OPT_rw_keep_user_macro - bool ExtractEntryUniforms = false; // OPT_rw_extract_entry_uniforms - bool RemoveUnusedGlobals = false; // OPT_rw_remove_unused_globals - bool RemoveUnusedFunctions = false; // OPT_rw_remove_unused_functions - bool WithLineDirective = false; // OPT_rw_line_directive - bool DeclGlobalCB = false; // OPT_rw_decl_global_cb + bool Unchanged = false; // OPT_rw_unchanged + bool ConsistentBindings = false; // OPT_rw_consistent_bindings + bool ReflectHLSLBasics = false; // OPT_rw_reflect_hlsl_basics + bool ReflectHLSLFunctions = false; // OPT_rw_reflect_hlsl_functions + bool ReflectHLSLNamespaces = false; // OPT_rw_reflect_hlsl_namespaces + bool ReflectHLSLUserTypes = false; // OPT_rw_reflect_hlsl_user_types + bool ReflectHLSLFunctionInternals = false; // OPT_rw_reflect_hlsl_function_internals + bool ReflectHLSLVariables = false; // OPT_rw_reflect_hlsl_variables + bool SkipFunctionBody = false; // OPT_rw_skip_function_body + bool SkipStatic = false; // OPT_rw_skip_static + bool GlobalExternByDefault = false; // OPT_rw_global_extern_by_default + bool KeepUserMacro = false; // OPT_rw_keep_user_macro + bool ExtractEntryUniforms = false; // OPT_rw_extract_entry_uniforms + bool RemoveUnusedGlobals = false; // OPT_rw_remove_unused_globals + bool RemoveUnusedFunctions = false; // OPT_rw_remove_unused_functions + bool WithLineDirective = false; // OPT_rw_line_directive + bool DeclGlobalCB = false; // OPT_rw_decl_global_cb }; /// Use this class to capture all options. diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index 2fe689a244..e7b36580eb 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -565,8 +565,18 @@ def rw_unchanged : Flag<["-", "/"], "unchanged">, Group, Flag HelpText<"Rewrite HLSL, without changes.">; def rw_consistent_bindings : Flag<["-", "/"], "consistent-bindings">, Group, Flags<[RewriteOption]>, HelpText<"Generate bindings for registers that aren't fully qualified (to have consistent bindings).">; -def rw_reflect_hlsl : Flag<["-", "/"], "reflect-hlsl">, Group, Flags<[RewriteOption]>, - HelpText<"Reflect HLSL and generate consistent bindings.">; +def rw_reflect_hlsl_basics : Flag<["-", "/"], "reflect-hlsl-basics">, Group, Flags<[RewriteOption]>, + HelpText<"Reflect HLSL (registers, constants and annotations) and generate consistent bindings.">; +def rw_reflect_hlsl_functions : Flag<["-", "/"], "reflect-hlsl-functions">, Group, Flags<[RewriteOption]>, + HelpText<"Reflect HLSL functions.">; +def rw_reflect_hlsl_namespaces : Flag<["-", "/"], "reflect-hlsl-namespaces">, Group, Flags<[RewriteOption]>, + HelpText<"Reflect HLSL nodes in namespaces rather than only the root namespace.">; +def rw_reflect_hlsl_user_types : Flag<["-", "/"], "reflect-hlsl-user-types">, Group, Flags<[RewriteOption]>, + HelpText<"Reflect HLSL user types (typedef, using, struct, enum).">; +def rw_reflect_hlsl_function_internals : Flag<["-", "/"], "reflect-hlsl-function-internals">, Group, Flags<[RewriteOption]>, + HelpText<"Reflect HLSL function internals (variables and structs defined in functions).">; +def rw_reflect_hlsl_variables : Flag<["-", "/"], "reflect-hlsl-variables">, Group, Flags<[RewriteOption]>, + HelpText<"Reflect HLSL static variables.">; def rw_skip_function_body : Flag<["-", "/"], "skip-fn-body">, Group, Flags<[RewriteOption]>, HelpText<"Translate function definitions to declarations">; def rw_skip_static : Flag<["-", "/"], "skip-static">, Group, Flags<[RewriteOption]>, diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index 535fae4c97..96a06d54e3 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -1351,8 +1351,18 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, opts.RWOpt.Unchanged = Args.hasFlag(OPT_rw_unchanged, OPT_INVALID, false); opts.RWOpt.ConsistentBindings = Args.hasFlag(OPT_rw_consistent_bindings, OPT_INVALID, false); - opts.RWOpt.ReflectHLSL = - Args.hasFlag(OPT_rw_reflect_hlsl, OPT_INVALID, false); + opts.RWOpt.ReflectHLSLBasics = + Args.hasFlag(OPT_rw_reflect_hlsl_basics, OPT_INVALID, false); + opts.RWOpt.ReflectHLSLFunctions = + Args.hasFlag(OPT_rw_reflect_hlsl_functions, OPT_INVALID, false); + opts.RWOpt.ReflectHLSLNamespaces = + Args.hasFlag(OPT_rw_reflect_hlsl_namespaces, OPT_INVALID, false); + opts.RWOpt.ReflectHLSLUserTypes = + Args.hasFlag(OPT_rw_reflect_hlsl_user_types, OPT_INVALID, false); + opts.RWOpt.ReflectHLSLFunctionInternals = + Args.hasFlag(OPT_rw_reflect_hlsl_function_internals, OPT_INVALID, false); + opts.RWOpt.ReflectHLSLVariables = + Args.hasFlag(OPT_rw_reflect_hlsl_variables, OPT_INVALID, false); opts.RWOpt.SkipFunctionBody = Args.hasFlag(OPT_rw_skip_function_body, OPT_INVALID, false); opts.RWOpt.SkipStatic = diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index d588c7a0c8..2042c29554 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -544,7 +544,7 @@ void SetupCompilerCommon(CompilerInstance &compiler, compiler.getDiagnostics().setWarningsAsErrors(true); compiler.getDiagnostics().setIgnoreAllWarnings(!opts.OutputWarnings); compiler.getLangOpts().HLSLVersion = opts.HLSLVersion; - compiler.getLangOpts().PreserveUnknownAnnotations = opts.RWOpt.ReflectHLSL; + compiler.getLangOpts().PreserveUnknownAnnotations = opts.RWOpt.ReflectHLSLBasics; compiler.getLangOpts().UseMinPrecision = !opts.Enable16BitTypes; compiler.getLangOpts().EnableDX9CompatMode = opts.EnableDX9CompatMode; compiler.getLangOpts().EnableFXCCompatMode = opts.EnableFXCCompatMode; @@ -1817,17 +1817,20 @@ static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, //It's a struct, add parameters recursively }*/ -enum InclusionFlag { - InclusionFlag_Default = 0, //Includes cbuffer and registers - InclusionFlag_Functions = 1 << 0, - InclusionFlag_Namespaces = 1 << 1, - InclusionFlag_UserTypes = 1 << 2, //Include user types (struct, enum, typedef, etc.) - InclusionFlag_FunctionInternals = 1 << 3, //Variables, structs, functions defined in functions - InclusionFlag_Variables = 1 << 4, //Variables not included in $Global or cbuffers - InclusionFlag_Annotations = 1 << 5, //Annotations e.g. [[myAnnotation]] for additional reflection - InclusionFlag_All = (1 << 6) - 1 +enum ReflectionMask : uint32_t { + ReflectionMask_None = 0, + ReflectionMask_Basics = 1 << 0, //Includes cbuffer and registers + ReflectionMask_Functions = 1 << 1, + ReflectionMask_Namespaces = 1 << 2, + ReflectionMask_UserTypes = 1 << 3, //Include user types (struct, enum, typedef, etc.) + ReflectionMask_FunctionInternals = 1 << 4, //Variables, structs, functions defined in functions + ReflectionMask_Variables = 1 << 5 //Variables not included in $Global or cbuffers }; +ReflectionMask& operator|=(ReflectionMask &a, ReflectionMask b) { + return a = (ReflectionMask)((uint32_t)a | (uint32_t)b); +} + class PrintfStream : public llvm::raw_ostream { public: PrintfStream() { SetUnbuffered(); } @@ -1847,7 +1850,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, - InclusionFlag InclusionFlags, + ReflectionMask InclusionFlags, uint32_t ParentNodeId) { /* @@ -1875,12 +1878,16 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, continue; if (HLSLBufferDecl *CBuffer = dyn_cast(it)) { + + if(!(InclusionFlags & ReflectionMask_Basics)) + continue; + //CBuffer->print(pfStream, printingPolicy); } else if (FunctionDecl *Func = dyn_cast(it)) { - if (!(InclusionFlags & InclusionFlag_Functions)) + if (!(InclusionFlags & ReflectionMask_Functions)) continue; const FunctionDecl *Definition = nullptr; @@ -1906,7 +1913,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, Refl.Functions.push_back(std::move(func)); - if (hasDefinition && (InclusionFlags & InclusionFlag_FunctionInternals)) { + if (hasDefinition && (InclusionFlags & ReflectionMask_FunctionInternals)) { RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, InclusionFlags, nodeId); @@ -1915,7 +1922,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (FieldDecl *Field = dyn_cast(it)) { - if (!(InclusionFlags & InclusionFlag_UserTypes)) + if (!(InclusionFlags & ReflectionMask_UserTypes)) continue; //Field->print(pfStream, printingPolicy); @@ -1923,7 +1930,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (TypedefDecl *Typedef = dyn_cast(it)) { - if (!(InclusionFlags & InclusionFlag_UserTypes)) + if (!(InclusionFlags & ReflectionMask_UserTypes)) continue; // Typedef->print(pfStream, printingPolicy); @@ -1931,7 +1938,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (TypeAliasDecl *TypeAlias = dyn_cast(it)) { - if (!(InclusionFlags & InclusionFlag_UserTypes)) + if (!(InclusionFlags & ReflectionMask_UserTypes)) continue; // TypeAlias->print(pfStream, printingPolicy); @@ -1939,7 +1946,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (EnumDecl *Enum = dyn_cast(it)) { - if (!(InclusionFlags & InclusionFlag_UserTypes)) + if (!(InclusionFlags & ReflectionMask_UserTypes)) continue; uint32_t nodeId = PushNextNodeId( @@ -1992,6 +1999,9 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (ValueDecl *ValDecl = dyn_cast(it)) { + if(!(InclusionFlags & ReflectionMask_Basics)) + continue; + //TODO: Handle values //ValDecl->print(pfStream); @@ -2022,7 +2032,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (RecordDecl *RecDecl = dyn_cast(it)) { - if (!(InclusionFlags & InclusionFlag_UserTypes)) + if (!(InclusionFlags & ReflectionMask_UserTypes)) continue; //RecDecl->print(pfStream, printingPolicy); @@ -2032,7 +2042,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (NamespaceDecl *Namespace = dyn_cast(it)) { - if (!(InclusionFlags & InclusionFlag_Namespaces)) + if (!(InclusionFlags & ReflectionMask_Namespaces)) continue; uint32_t nodeId = PushNextNodeId( @@ -2046,7 +2056,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, } static void ReflectHLSL(ASTHelper &astHelper, ReflectionData& Refl, - uint32_t AutoBindingSpace) { + uint32_t AutoBindingSpace, ReflectionMask ReflectMask) { TranslationUnitDecl &Ctx = *astHelper.tu; DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); @@ -2061,7 +2071,7 @@ static void ReflectHLSL(ASTHelper &astHelper, ReflectionData& Refl, }); RecursiveReflectHLSL(Ctx, astHelper.compiler.getASTContext(), Diags, SM, Refl, - AutoBindingSpace, 0, InclusionFlag_All, 0); + AutoBindingSpace, 0, ReflectMask, 0); } static void GlobalVariableAsExternByDefault(DeclContext &Ctx) { @@ -2176,13 +2186,34 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, TranslationUnitDecl *tu = astHelper.tu; - if (opts.RWOpt.ConsistentBindings || opts.RWOpt.ReflectHLSL) { + if (opts.RWOpt.ConsistentBindings || opts.RWOpt.ReflectHLSLBasics) { GenerateConsistentBindings(*tu, opts.AutoBindingSpace); } - if (opts.RWOpt.ReflectHLSL) { + ReflectionMask reflectMask = ReflectionMask_None; + + if(opts.RWOpt.ReflectHLSLBasics) + reflectMask |= ReflectionMask_Basics; + + if(opts.RWOpt.ReflectHLSLFunctions) + reflectMask |= ReflectionMask_Functions; + + if(opts.RWOpt.ReflectHLSLNamespaces) + reflectMask |= ReflectionMask_Namespaces; + + if(opts.RWOpt.ReflectHLSLUserTypes) + reflectMask |= ReflectionMask_UserTypes; + + if(opts.RWOpt.ReflectHLSLFunctionInternals) + reflectMask |= ReflectionMask_FunctionInternals; + + if(opts.RWOpt.ReflectHLSLVariables) + reflectMask |= ReflectionMask_Variables; + + if (reflectMask) { + ReflectionData Refl; - ReflectHLSL(astHelper, Refl, opts.AutoBindingSpace); + ReflectHLSL(astHelper, Refl, opts.AutoBindingSpace, reflectMask); for (DxcHLSLEnumDesc en : Refl.Enums) { @@ -2240,7 +2271,7 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, opts.RWOpt.RemoveUnusedFunctions, w); if (FAILED(hr)) return hr; - } else if (!opts.RWOpt.ConsistentBindings && !opts.RWOpt.ReflectHLSL) { + } else if (!opts.RWOpt.ConsistentBindings && (reflectMask & ReflectionMask_Basics)) { o << "// Rewrite unchanged result:\n"; } From a520504e11022f34dc7931329d9a94d9bcc183ee Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Thu, 14 Aug 2025 22:05:27 +0200 Subject: [PATCH 012/126] Started defining DxcHLSLParameter, pretty close to finishing DxcHLSLRegister and started defining type, variable and 'constant buffer'. --- .../clang/tools/libclang/dxcrewriteunused.cpp | 534 +++++++++++++++--- 1 file changed, 471 insertions(+), 63 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 2042c29554..96995e2c74 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1282,7 +1282,6 @@ static void GenerateConsistentBindings(DeclContext &Ctx, enum class DxcHLSLNodeType : uint64_t { Register, - CBuffer, Function, Enum, EnumValue, @@ -1290,7 +1289,8 @@ enum class DxcHLSLNodeType : uint64_t { Typedef, Using, Variable, - Parameter + Parameter, + Type }; struct DxcHLSLNode { @@ -1323,17 +1323,20 @@ struct DxcHLSLEnumValue { uint32_t NodeId; }; -struct DxcHLSLParameter { //Mirrors D3D12_PARAMETER_DESC (ex. First(In/Out)(Register/Component)), but with std::string and NodeId +struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC (ex. + // First(In/Out)(Register/Component)), but with + // std::string and NodeId + std::string SemanticName; - D3D_SHADER_VARIABLE_TYPE Type; // Element type. - D3D_SHADER_VARIABLE_CLASS Class; // Scalar/Vector/Matrix. - uint32_t Rows; // Rows are for matrix parameters. - uint32_t Columns; // Components or Columns in matrix. - D3D_INTERPOLATION_MODE InterpolationMode; // Interpolation mode. - D3D_PARAMETER_FLAGS Flags; // Parameter modifiers. + D3D_SHADER_VARIABLE_TYPE Type; // Element type. + D3D_SHADER_VARIABLE_CLASS Class; // Scalar/Vector/Matrix. + uint32_t Rows; // Rows are for matrix parameters. + uint32_t Columns; // Components or Columns in matrix. + D3D_INTERPOLATION_MODE InterpolationMode; // Interpolation mode. + D3D_PARAMETER_FLAGS Flags; // Parameter modifiers. uint32_t NodeId; - //TODO: Array info + // TODO: Array info }; struct DxcHLSLFunction { @@ -1343,24 +1346,96 @@ struct DxcHLSLFunction { uint32_t HasDefinition : 1; }; -struct DxcHLSLRegister { //Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus the Name (and uID replaced with NodeID) and added arrayIndex +struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus + // the Name (and uID replaced with NodeID) and added + // arrayIndex - D3D_SHADER_INPUT_TYPE Type; // Type of resource (e.g. texture, cbuffer, etc.) - uint32_t BindPoint; // Starting bind point - uint32_t BindCount; // Number of contiguous bind points (for arrays) + D3D_SHADER_INPUT_TYPE Type; // Type of resource (e.g. texture, cbuffer, etc.) + uint32_t BindPoint; // Starting bind point + uint32_t BindCount; // Number of contiguous bind points (for arrays) - uint32_t uFlags; // Input binding flags - D3D_RESOURCE_RETURN_TYPE ReturnType; // Return type (if texture) - D3D_SRV_DIMENSION Dimension; // Dimension (if texture) - uint32_t NumSamples; // Number of samples (0 if not MS texture) - uint32_t Space; // Register space - uint32_t NodeId; - uint32_t ArrayId; // Only accessible if BindCount > 1 and the array is multi dimensional + uint32_t uFlags; // Input binding flags + D3D_RESOURCE_RETURN_TYPE ReturnType; // Return type (if texture) + D3D_SRV_DIMENSION Dimension; // Dimension (if texture) + uint32_t NumSamples; // Number of samples (0 if not MS texture) + uint32_t Space; // Register space + uint32_t NodeId; + uint32_t ArrayId; // Only accessible if BindCount > 1 and the array is multi + // dimensional + uint32_t BufferId; //If cbuffer or structured buffer }; -struct DxcHLSLArray { - uint32_t ArrayElem : 4; // Array of up to 8 recursion levels deep (like spirv) - uint32_t ArrayStart : 28; // Index into ArraySizes with ArraySize +union DxcHLSLArray { + + struct { + uint32_t ArrayElem : 4; // Array of up to 8 deep (like spirv) + uint32_t ArrayStart : 28; // Index into ArraySizes with ArraySize + }; + + uint32_t Data; + + bool operator==(const DxcHLSLArray &Other) const { + return Other.Data == Data; + } +}; + +struct DxcHLSLType { // Almost maps to CShaderReflectionType and + // D3D12_SHADER_TYPE_DESC, except tightly packed and + // relatively serializable + + std::string Name; // Can be empty + std::vector MemberTypes; + std::vector Interfaces; + + union { + struct { + D3D_SHADER_VARIABLE_CLASS Class : 8; + D3D_SHADER_VARIABLE_TYPE Type : 8; + uint32_t Rows : 8; + uint32_t Columns : 8; + }; + uint32_t ClassTypeRowsColums; + }; + + union { + uint32_t ElementsOrArrayId; + struct { + uint32_t HasArrayInfo0 : 1; // If 0, indicates that elements represents 1D + // array + uint32_t Elements : 31; // Number of elements (0 if not an array) + }; + struct { + uint32_t HasArrayInfo1 : 1; // If 1, indicates that elements represents + // multi dimensional array + uint32_t ArrayId : 31; // Array id + }; + }; + + uint32_t BaseClass; // -1 if none, otherwise a type index + uint32_t SubType; // -1 if none, otherwise a type index + + bool operator==(const DxcHLSLType &Other) const { + return Other.Name == Name && Other.MemberTypes == MemberTypes && + Other.Interfaces == Interfaces && + ClassTypeRowsColums == Other.ClassTypeRowsColums && + ElementsOrArrayId == Other.ElementsOrArrayId && + BaseClass == Other.BaseClass && SubType == Other.SubType; + } +}; + +struct DxcHLSLVariable { // Almost maps to CShaderReflectionVariable and + // D3D12_SHADER_VARIABLE_DESC, but tightly packed and + // easily serializable + + uint32_t ConstantBuffer; + uint32_t Type; + + std::string Name; // Can be empty + + bool operator==(const DxcHLSLVariable &Other) const { + return Other.ConstantBuffer == ConstantBuffer && Other.Type == Type && + Other.Name == Name; + } }; struct DxcRegisterTypeInfo { @@ -1371,7 +1446,15 @@ struct DxcRegisterTypeInfo { uint32_t SampleCount; }; -struct ReflectionData { +struct DxcHLSLBuffer { //Almost maps to CShaderReflectionConstantBuffer and D3D12_SHADER_BUFFER_DESC + + std::vector Variables; + + D3D_CBUFFER_TYPE Type; + uint32_t NodeId; +}; + +struct DxcReflectionData { std::vector Nodes; //0 = Root node (global scope) std::vector Sources; std::unordered_map SourceToFileId; @@ -1383,9 +1466,12 @@ struct ReflectionData { std::vector Annotations; std::vector Arrays; std::vector ArraySizes; + std::vector Types; + std::vector Variables; + std::vector Buffers; }; -static uint32_t PushNextNodeId(ReflectionData &Refl, const SourceManager &SM, +static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, const LangOptions &LangOpts, const std::string &UnqualifiedName, Decl *Decl, DxcHLSLNodeType Type, uint32_t ParentNodeId, @@ -1691,13 +1777,13 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); } -static uint32_t PushArray(ReflectionData &Refl, uint32_t ArraySizeFlat, +static uint32_t PushArray(DxcReflectionData &Refl, uint32_t ArraySizeFlat, const std::vector &ArraySize) { if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) return (uint32_t)-1; - assert(Refl.Arrays.size() < (uint32_t)-1 && "Arrays would overflow"); + assert(Refl.Arrays.size() < (uint32_t)((1u << 31) - 1) && "Arrays would overflow"); uint32_t arrayId = (uint32_t)Refl.Arrays.size(); uint32_t arrayCountStart = (uint32_t)Refl.ArraySizes.size(); @@ -1717,7 +1803,13 @@ static uint32_t PushArray(ReflectionData &Refl, uint32_t ArraySizeFlat, Refl.ArraySizes.push_back(arraySize); } - Refl.Arrays.push_back({numArrayElements, arrayCountStart}); + DxcHLSLArray arr = {numArrayElements, arrayCountStart}; + + for (uint32_t i = 0; i < Refl.Arrays.size(); ++i) + if (Refl.Arrays[i] == arr) + return i; + + Refl.Arrays.push_back(arr); return arrayId; } @@ -1725,7 +1817,7 @@ static void FillReflectionRegisterAt( const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, ValueDecl *ValDesc, const std::vector &ArraySize, - ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId) { + DxcReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId) { ArrayRef UA = ValDesc->getUnusualAnnotations(); @@ -1768,9 +1860,292 @@ static void FillReflectionRegisterAt( Refl.Registers.push_back(regD3D12); } +class PrintfStream : public llvm::raw_ostream { +public: + PrintfStream() { SetUnbuffered(); } + +private: + void write_impl(const char *Ptr, size_t Size) override { + printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly + } + + uint64_t current_pos() const override { return 0; } +}; + +uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, + Decl *Decl, bool DefaultRowMaj) { + + ValueDecl *valDecl = dyn_cast(Decl); + assert(valDecl && "Decl was expected to be a ValueDecl but wasn't"); + + DxcHLSLType type = {}; + + // Name; Omit struct, class and const keywords + + PrintingPolicy policy(valDecl->getASTContext().getLangOpts()); + policy.SuppressScope = false; + policy.AnonymousTagLocations = false; + policy.SuppressTagKeyword = true; + + type.Name = valDecl->getType().getLocalUnqualifiedType().getAsString(policy); + + // Unwrap array + + uint32_t arraySize = 1; + QualType underlying = valDecl->getType(); + QualType original = underlying; + std::vector arrayElem; + + while (const ConstantArrayType *arr = + dyn_cast(underlying)) { + uint32_t current = arr->getSize().getZExtValue(); + arrayElem.push_back(current); + arraySize *= arr->getSize().getZExtValue(); + underlying = arr->getElementType(); + + type.Name = + underlying.getLocalUnqualifiedType().getAsString(policy); + + underlying = underlying.getCanonicalType(); + } + + underlying = underlying.getCanonicalType(); + + uint32_t arrayId = PushArray(Refl, arraySize, arrayElem); + + if (arrayId != (uint32_t)-1) { + type.HasArrayInfo1 = 1; + type.ArrayId = arrayId; + } + + else { + type.HasArrayInfo1 = 0; + type.Elements = arraySize > 1 ? arraySize : 0; + } + + //Unwrap vector and matrix + + type.Class = D3D_SVC_STRUCT; + + if (const RecordType *record = + underlying->getAs()) { + + if (const ClassTemplateSpecializationDecl *templateClass = + dyn_cast(record->getDecl())) { + + const std::string &name = templateClass->getIdentifier()->getName(); + + const ArrayRef ¶ms = + templateClass->getTemplateArgs().asArray(); + + uint32_t magic = 0; + std::memcpy(&magic, name.c_str(), std::min(sizeof(magic), name.size())); + + std::string_view subs = + name.size() < sizeof(magic) + ? std::string_view() + : std::string_view(name).substr(sizeof(magic)); + + switch (magic) { + + case DXC_FOURCC('v', 'e', 'c', 't'): + + if (subs == "or") { + + type.Rows = 1; + + assert(params.size() == 2 && !params[0].getAsType().isNull() && + params[1].getKind() == TemplateArgument::Integral && + "Expected vector to be vector"); + + underlying = params[0].getAsType(); + type.Columns = params[1].getAsIntegral().getSExtValue(); + type.Class = D3D_SVC_VECTOR; + } + + break; + + case DXC_FOURCC('m', 'a', 't', 'r'): + + if (subs == "ix") { + + assert(params.size() == 3 && !params[0].getAsType().isNull() && + params[1].getKind() == TemplateArgument::Integral && + params[2].getKind() == TemplateArgument::Integral && + "Expected matrix to be matrix"); + + underlying = params[0].getAsType(); + type.Columns = params[1].getAsIntegral().getSExtValue(); + type.Rows = params[2].getAsIntegral().getSExtValue(); + + bool isRowMajor = DefaultRowMaj; + + HasHLSLMatOrientation(original, &isRowMajor); + + if (!isRowMajor) { + uint32_t rows = type.Rows; + type.Rows = type.Columns; + type.Columns = rows; + } + + type.Class = + isRowMajor ? D3D_SVC_MATRIX_ROWS : D3D_SVC_MATRIX_COLUMNS; + } + + break; + } + } + } + + //Type name + + if (const BuiltinType *bt = dyn_cast(underlying)) { + + if (!type.Rows) + type.Rows = type.Columns = 1; + + if (type.Class == D3D_SVC_STRUCT) + type.Class = D3D_SVC_SCALAR; + + switch (bt->getKind()) { + + case BuiltinType::Void: + type.Type = D3D_SVT_VOID; + break; + + case BuiltinType::Min10Float: + type.Type = D3D_SVT_MIN10FLOAT; + break; + + case BuiltinType::Min16Float: + type.Type = D3D_SVT_MIN16FLOAT; + break; + + case BuiltinType::HalfFloat: + case BuiltinType::Half: + type.Type = D3D_SVT_FLOAT16; + break; + + case BuiltinType::Short: + type.Type = D3D_SVT_INT16; + break; + + case BuiltinType::Min12Int: + type.Type = D3D_SVT_MIN12INT; + break; + + case BuiltinType::Min16Int: + type.Type = D3D_SVT_MIN16INT; + break; + + case BuiltinType::Min16UInt: + type.Type = D3D_SVT_MIN16UINT; + break; + + case BuiltinType::UShort: + type.Type = D3D_SVT_UINT16; + break; + + case BuiltinType::Float: + type.Type = D3D_SVT_FLOAT; + break; + + case BuiltinType::Int: + type.Type = D3D_SVT_INT; + break; + + case BuiltinType::UInt: + type.Type = D3D_SVT_UINT; + break; + + case BuiltinType::Bool: + type.Type = D3D_SVT_BOOL; + break; + + case BuiltinType::Double: + type.Type = D3D_SVT_DOUBLE; + break; + + case BuiltinType::ULongLong: + type.Type = D3D_SVT_UINT64; + break; + + case BuiltinType::LongLong: + type.Type = D3D_SVT_INT64; + break; + + default: + assert(false && "Invalid builtin type"); + break; + } + } + + assert(Refl.Types.size() < (uint32_t)-1 && "Type id out of bounds"); + + uint32_t i = 0, j = (uint32_t)Refl.Types.size(); + + for (; i < j; ++i) + if (Refl.Types[i] == type) + break; + + if (i == j) + Refl.Types.push_back(type); + + return i; +} + +std::vector RecurseBuffer(ASTContext &ASTCtx, DxcReflectionData &Refl, + DeclContext *Buffer, uint32_t BufferId, + bool DefaultRowMaj) { + + std::vector variables; + + for (Decl *decl : Buffer->decls()) { + + DxcHLSLVariable variable = {BufferId}; + + if (NamedDecl *named = dyn_cast(decl)) + variable.Name = named->getName(); + + variable.Type = GenerateTypeInfo(ASTCtx, Refl, decl, DefaultRowMaj); + assert(Refl.Variables.size() < (uint32_t)-1 && "Variable id out of bounds"); + + uint32_t i = 0, j = (uint32_t)Refl.Variables.size(); + + for (; i < j; ++i) + if (Refl.Variables[i] == variable) + break; + + if (i == j) + Refl.Variables.push_back(variable); + + variables.push_back(i); + } + + return variables; +} + +uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcReflectionData &Refl, + DeclContext *Buffer, uint32_t NodeId, + D3D_CBUFFER_TYPE Type, bool DefaultRowMaj) { + + assert(Refl.Buffers.size() < (uint32_t)-1 && "Buffer id out of bounds"); + uint32_t bufferId = (uint32_t)Refl.Buffers.size(); + + std::vector variables = + RecurseBuffer(ASTCtx, Refl, Buffer, bufferId, DefaultRowMaj); + + Refl.Buffers.push_back({ + variables, + Type, + NodeId}); + + return bufferId; +} + /* static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, - ReflectionData &Refl, const SourceManager &SM, + DxcReflectionData &Refl, const SourceManager &SM, uint32_t ParentNodeId) { PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); @@ -1831,29 +2206,15 @@ ReflectionMask& operator|=(ReflectionMask &a, ReflectionMask b) { return a = (ReflectionMask)((uint32_t)a | (uint32_t)b); } -class PrintfStream : public llvm::raw_ostream { -public: - PrintfStream() { SetUnbuffered(); } - -private: - void write_impl(const char *Ptr, size_t Size) override { - printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly - } - - uint64_t current_pos() const override { return 0; } -}; - - static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, - ReflectionData &Refl, + DxcReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, ReflectionMask InclusionFlags, - uint32_t ParentNodeId) { + uint32_t ParentNodeId, bool DefaultRowMaj) { - /* PrintfStream pfStream; PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); @@ -1864,7 +2225,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, true; // No inheritance list, trailing semicolons, etc. printingPolicy.PolishForDeclaration = true; // Makes it print as a decl printingPolicy.SuppressSpecifiers = false; // Prints e.g. "static" or "inline" - printingPolicy.SuppressScope = true;*/ + printingPolicy.SuppressScope = true; // Traverse AST to grab reflection data @@ -1881,8 +2242,52 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if(!(InclusionFlags & ReflectionMask_Basics)) continue; + + // TODO: Add for reflection even though it might not be important + + if (Depth != 0) + continue; - //CBuffer->print(pfStream, printingPolicy); + hlsl::RegisterAssignment *reg = nullptr; + ArrayRef UA = CBuffer->getUnusualAnnotations(); + + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { + + if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) + continue; + + reg = cast(*It); + } + + assert(reg && + "Found a cbuffer missing a RegisterAssignment, even though " + "GenerateConsistentBindings should have already generated it"); + + uint32_t nodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), CBuffer->getName(), + CBuffer, DxcHLSLNodeType::Register, ParentNodeId, + (uint32_t)Refl.Registers.size()); + + uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, CBuffer, nodeId, + D3D_CT_CBUFFER, DefaultRowMaj); + + DxcHLSLRegister regD3D12 = { + + D3D_SIT_CBUFFER, + reg->RegisterNumber, + 1, + (uint32_t) D3D_SIF_USERPACKED, + (D3D_RESOURCE_RETURN_TYPE) 0, + D3D_SRV_DIMENSION_UNKNOWN, + 0, + reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() + : AutoBindingSpace, + nodeId, + (uint32_t)-1, + bufferId + }; + + Refl.Registers.push_back(regD3D12); } else if (FunctionDecl *Func = dyn_cast(it)) { @@ -1916,7 +2321,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (hasDefinition && (InclusionFlags & ReflectionMask_FunctionInternals)) { RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, InclusionFlags, - nodeId); + nodeId, DefaultRowMaj); } } @@ -2021,9 +2426,9 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!IsHLSLResourceType(type)) continue; - //ValDecl->print(pfStream, printingPolicy); + // TODO: Add for reflection even though it might not be important - if (Depth != 0) //TODO: Add for reflection even though it might not be important + if (Depth != 0) continue; FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, ValDecl, @@ -2050,13 +2455,15 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DxcHLSLNodeType::Namespace, ParentNodeId, 0); RecursiveReflectHLSL(*Namespace, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, InclusionFlags, nodeId); + AutoBindingSpace, Depth + 1, InclusionFlags, nodeId, + DefaultRowMaj); } } } -static void ReflectHLSL(ASTHelper &astHelper, ReflectionData& Refl, - uint32_t AutoBindingSpace, ReflectionMask ReflectMask) { +static void ReflectHLSL(ASTHelper &astHelper, DxcReflectionData& Refl, + uint32_t AutoBindingSpace, ReflectionMask ReflectMask, + bool DefaultRowMaj) { TranslationUnitDecl &Ctx = *astHelper.tu; DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); @@ -2071,7 +2478,7 @@ static void ReflectHLSL(ASTHelper &astHelper, ReflectionData& Refl, }); RecursiveReflectHLSL(Ctx, astHelper.compiler.getASTContext(), Diags, SM, Refl, - AutoBindingSpace, 0, ReflectMask, 0); + AutoBindingSpace, 0, ReflectMask, 0, DefaultRowMaj); } static void GlobalVariableAsExternByDefault(DeclContext &Ctx) { @@ -2115,7 +2522,7 @@ char RegisterGetSpaceChar(const DxcHLSLRegister ®) { } } -std::string RegisterGetArraySize(const ReflectionData &Refl, const DxcHLSLRegister ®) { +std::string RegisterGetArraySize(const DxcReflectionData &Refl, const DxcHLSLRegister ®) { if (reg.ArrayId != (uint32_t)-1) { @@ -2142,14 +2549,14 @@ std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { std::string NodeTypeToString(DxcHLSLNodeType type) { - const char *arr[] = {"Register", "CBuffer", "Function", "Enum", - "EnumValue", "Namespace", "Typedef", "Using", - "Variable", "Parameter"}; + const char *arr[] = {"Register", "Function", "Enum", + "EnumValue", "Namespace", "Typedef", "Using", "Variable", + "Parameter", "Type" }; return arr[(int)type]; } -uint32_t RecursePrint(const ReflectionData &Refl, uint32_t NodeId, +uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, uint32_t Depth) { const DxcHLSLNode &node = Refl.Nodes[NodeId]; @@ -2212,8 +2619,9 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, if (reflectMask) { - ReflectionData Refl; - ReflectHLSL(astHelper, Refl, opts.AutoBindingSpace, reflectMask); + DxcReflectionData Refl; + ReflectHLSL(astHelper, Refl, opts.AutoBindingSpace, reflectMask, + opts.DefaultRowMajor); for (DxcHLSLEnumDesc en : Refl.Enums) { From 4c572c0979b16d4cf0e445bf5f16df0e3d3fd884 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Thu, 14 Aug 2025 23:40:15 +0200 Subject: [PATCH 013/126] Now storing strings as an index, now handling arrays of sugared types correctly, added some todos and empty string is now specified as string id 0. Now printing test through node iteration. --- .../clang/tools/libclang/dxcrewriteunused.cpp | 232 ++++++++++++------ 1 file changed, 154 insertions(+), 78 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 96995e2c74..66a076453b 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1295,7 +1295,8 @@ enum class DxcHLSLNodeType : uint64_t { struct DxcHLSLNode { - std::string Name; // Local name (not including parent's name) + uint32_t NameId; // Local name (not including parent's name) + uint32_t SourceScopeInfo; // TODO: DxcHLSLNodeType NodeType : 4; uint64_t LocalId : 24; // For example if Enum, maps into Enums[LocalId] @@ -1383,7 +1384,7 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and // D3D12_SHADER_TYPE_DESC, except tightly packed and // relatively serializable - std::string Name; // Can be empty + uint32_t NameId; //Can be empty std::vector MemberTypes; std::vector Interfaces; @@ -1415,7 +1416,7 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and uint32_t SubType; // -1 if none, otherwise a type index bool operator==(const DxcHLSLType &Other) const { - return Other.Name == Name && Other.MemberTypes == MemberTypes && + return Other.NameId == NameId && Other.MemberTypes == MemberTypes && Other.Interfaces == Interfaces && ClassTypeRowsColums == Other.ClassTypeRowsColums && ElementsOrArrayId == Other.ElementsOrArrayId && @@ -1429,12 +1430,11 @@ struct DxcHLSLVariable { // Almost maps to CShaderReflectionVariable and uint32_t ConstantBuffer; uint32_t Type; - - std::string Name; // Can be empty + uint32_t NameId; // Can be empty bool operator==(const DxcHLSLVariable &Other) const { return Other.ConstantBuffer == ConstantBuffer && Other.Type == Type && - Other.Name == Name; + Other.NameId == NameId; } }; @@ -1455,22 +1455,49 @@ struct DxcHLSLBuffer { //Almost maps to CShaderReflectionConstantBuffer and }; struct DxcReflectionData { + + std::vector Strings; + std::unordered_map StringsToId; + + std::vector Sources; + std::unordered_map StringToSourceId; + std::vector Nodes; //0 = Root node (global scope) - std::vector Sources; - std::unordered_map SourceToFileId; + std::vector Registers; std::vector Functions; + std::vector Enums; std::vector EnumValues; + std::vector Parameters; - std::vector Annotations; + std::vector Annotations; + std::vector Arrays; std::vector ArraySizes; + std::vector Types; std::vector Variables; std::vector Buffers; }; +static uint32_t RegisterString(DxcReflectionData &Refl, + const std::string &Name) { + + assert(Refl.Strings.size() < (uint32_t)-1 && "Strings overflow"); + + auto it = Refl.StringsToId.find(Name); + + if (it != Refl.StringsToId.end()) + return it->second; + + uint32_t stringId = (uint32_t) Refl.Strings.size(); + + Refl.Strings.push_back(Name); + Refl.StringsToId[Name] = stringId; + return stringId; +} + static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, const LangOptions &LangOpts, const std::string &UnqualifiedName, Decl *Decl, @@ -1489,7 +1516,8 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, for (const Attr *attr : Decl->attrs()) { if (const AnnotateAttr *annotate = dyn_cast(attr)) { assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); - Refl.Annotations.push_back(annotate->getAnnotation().str()); + Refl.Annotations.push_back( + RegisterString(Refl, annotate->getAnnotation().str())); ++annotationCount; } } @@ -1527,13 +1555,13 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, assert(fileName == presumedEnd.getFilename() && "End and start are not in the same file"); - auto it = Refl.SourceToFileId.find(fileName); + auto it = Refl.StringToSourceId.find(fileName); uint32_t i; - if (it == Refl.SourceToFileId.end()) { + if (it == Refl.StringToSourceId.end()) { i = (uint32_t)Refl.Sources.size(); - Refl.Sources.push_back(fileName); - Refl.SourceToFileId[fileName] = i; + Refl.Sources.push_back(RegisterString(Refl, fileName)); + Refl.StringToSourceId[fileName] = i; } else { @@ -1555,10 +1583,11 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, } } - Refl.Nodes.push_back({UnqualifiedName, Type, LocalId, annotationStart, - fileNameId, 0, ParentNodeId, sourceLineCount, - sourceLineStart, sourceColumnStart, sourceColumnEnd, - annotationCount}); + uint32_t nameId = RegisterString(Refl, UnqualifiedName); + + Refl.Nodes.push_back({nameId, 0, Type, LocalId, annotationStart, fileNameId, + 0, ParentNodeId, sourceLineCount, sourceLineStart, + sourceColumnStart, sourceColumnEnd, annotationCount}); uint32_t parentParent = ParentNodeId; @@ -1879,21 +1908,12 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, assert(valDecl && "Decl was expected to be a ValueDecl but wasn't"); DxcHLSLType type = {}; - - // Name; Omit struct, class and const keywords - - PrintingPolicy policy(valDecl->getASTContext().getLangOpts()); - policy.SuppressScope = false; - policy.AnonymousTagLocations = false; - policy.SuppressTagKeyword = true; - - type.Name = valDecl->getType().getLocalUnqualifiedType().getAsString(policy); + QualType original = valDecl->getType(); // Unwrap array uint32_t arraySize = 1; - QualType underlying = valDecl->getType(); - QualType original = underlying; + QualType underlying = original, forName = original; std::vector arrayElem; while (const ConstantArrayType *arr = @@ -1901,16 +1921,21 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, uint32_t current = arr->getSize().getZExtValue(); arrayElem.push_back(current); arraySize *= arr->getSize().getZExtValue(); - underlying = arr->getElementType(); - - type.Name = - underlying.getLocalUnqualifiedType().getAsString(policy); - - underlying = underlying.getCanonicalType(); + forName = arr->getElementType(); + underlying = forName.getCanonicalType(); } underlying = underlying.getCanonicalType(); + // Name; Omit struct, class and const keywords + + PrintingPolicy policy(valDecl->getASTContext().getLangOpts()); + policy.SuppressScope = false; + policy.AnonymousTagLocations = false; + policy.SuppressTagKeyword = true; + + type.NameId = RegisterString(Refl, forName.getLocalUnqualifiedType().getAsString(policy)); + uint32_t arrayId = PushArray(Refl, arraySize, arrayElem); if (arrayId != (uint32_t)-1) { @@ -1927,8 +1952,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, type.Class = D3D_SVC_STRUCT; - if (const RecordType *record = - underlying->getAs()) { + if (const RecordType *record = underlying->getAs()) { if (const ClassTemplateSpecializationDecl *templateClass = dyn_cast(record->getDecl())) { @@ -1994,6 +2018,38 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, break; } + + // TODO: + // D3D_SVT_TEXTURE = 5, + // D3D_SVT_TEXTURE1D = 6, + // D3D_SVT_TEXTURE2D = 7, + // D3D_SVT_TEXTURE3D = 8, + // D3D_SVT_TEXTURECUBE = 9, + // D3D_SVT_SAMPLER = 10, + // D3D_SVT_SAMPLER1D = 11, + // D3D_SVT_SAMPLER2D = 12, + // D3D_SVT_SAMPLER3D = 13, + // D3D_SVT_SAMPLERCUBE = 14, + // D3D_SVT_BUFFER = 25, + // D3D_SVT_CBUFFER = 26, + // D3D_SVT_TBUFFER = 27, + // D3D_SVT_TEXTURE1DARRAY = 28, + // D3D_SVT_TEXTURE2DARRAY = 29, + // D3D_SVT_TEXTURE2DMS = 32, + // D3D_SVT_TEXTURE2DMSARRAY = 33, + // D3D_SVT_TEXTURECUBEARRAY = 34, + // D3D_SVT_RWTEXTURE1D = 40, + // D3D_SVT_RWTEXTURE1DARRAY = 41, + // D3D_SVT_RWTEXTURE2D = 42, + // D3D_SVT_RWTEXTURE2DARRAY = 43, + // D3D_SVT_RWTEXTURE3D = 44, + // D3D_SVT_RWBUFFER = 45, + // D3D_SVT_BYTEADDRESS_BUFFER = 46, + // D3D_SVT_RWBYTEADDRESS_BUFFER = 47, + // D3D_SVT_STRUCTURED_BUFFER = 48, + // D3D_SVT_RWSTRUCTURED_BUFFER = 49, + // D3D_SVT_APPEND_STRUCTURED_BUFFER = 50, + // D3D_SVT_CONSUME_STRUCTURED_BUFFER = 51, } } @@ -2080,6 +2136,10 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, } } + //TODO: Struct recurse + + //TODO: Interfaces, base class + assert(Refl.Types.size() < (uint32_t)-1 && "Type id out of bounds"); uint32_t i = 0, j = (uint32_t)Refl.Types.size(); @@ -2105,7 +2165,7 @@ std::vector RecurseBuffer(ASTContext &ASTCtx, DxcReflectionData &Refl, DxcHLSLVariable variable = {BufferId}; if (NamedDecl *named = dyn_cast(decl)) - variable.Name = named->getName(); + variable.NameId = RegisterString(Refl, named->getName()); variable.Type = GenerateTypeInfo(ASTCtx, Refl, decl, DefaultRowMaj); assert(Refl.Variables.size() < (uint32_t)-1 && "Variable id out of bounds"); @@ -2469,8 +2529,11 @@ static void ReflectHLSL(ASTHelper &astHelper, DxcReflectionData& Refl, DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); const SourceManager &SM = astHelper.compiler.getSourceManager(); + Refl.Strings.push_back(""); + Refl.StringsToId[""] = 0; + Refl.Nodes.push_back({ - "", + 0, 0, DxcHLSLNodeType::Namespace, 0, 0, @@ -2557,22 +2620,68 @@ std::string NodeTypeToString(DxcHLSLNodeType type) { } uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, - uint32_t Depth) { + uint32_t Depth, uint32_t IndexInParent) { const DxcHLSLNode &node = Refl.Nodes[NodeId]; if (NodeId) { printf("%s%s %s\n", std::string(Depth - 1, '\t').c_str(), - NodeTypeToString(node.NodeType).c_str(), node.Name.c_str()); + NodeTypeToString(node.NodeType).c_str(), + Refl.Strings[node.NameId].c_str()); for (uint32_t i = 0; i < node.AnnotationCount; ++i) printf("%s[[%s]]\n", std::string(Depth, '\t').c_str(), - Refl.Annotations[i].c_str()); + Refl.Strings[Refl.Annotations[i]].c_str()); + + switch (node.NodeType) { + + case DxcHLSLNodeType::Register: { + const DxcHLSLRegister ® = Refl.Registers[node.LocalId]; + printf("%s%s : register(%c%u, space%u);\n", + std::string(Depth, '\t').c_str(), + RegisterGetArraySize(Refl, reg).c_str(), RegisterGetSpaceChar(reg), + reg.BindPoint, reg.Space); + break; + } + + case DxcHLSLNodeType::Function: { + const DxcHLSLFunction &func = Refl.Functions[node.LocalId]; + printf("%sreturn: %s, hasDefinition: %s, numParams: %u\n", + std::string(Depth, '\t').c_str(), + func.HasReturn ? "true" : "false", + func.HasDefinition ? "true" : "false", func.NumParameters); + + break; + } + + case DxcHLSLNodeType::Enum: + printf("%s: %s\n", std::string(Depth, '\t').c_str(), + EnumTypeToString(Refl.Enums[node.LocalId].Type).c_str()); + break; + + case DxcHLSLNodeType::EnumValue: { + printf("%s#%u = %" PRIi64 "\n", std::string(Depth, '\t').c_str(), + IndexInParent, Refl.EnumValues[node.LocalId].Value); + break; + } + + //TODO: + case DxcHLSLNodeType::Type: + case DxcHLSLNodeType::Typedef: + case DxcHLSLNodeType::Using: + case DxcHLSLNodeType::Variable: + case DxcHLSLNodeType::Parameter: + break; + + case DxcHLSLNodeType::Namespace: + default: + break; + } } - for (uint32_t i = 0; i < node.ChildCount; ++i) - i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1); + for (uint32_t i = 0, j = 0; i < node.ChildCount; ++i, ++j) + i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1, j); return node.ChildCount; } @@ -2622,41 +2731,8 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, DxcReflectionData Refl; ReflectHLSL(astHelper, Refl, opts.AutoBindingSpace, reflectMask, opts.DefaultRowMajor); - - for (DxcHLSLEnumDesc en : Refl.Enums) { - - printf("Enum: %s (: %s)\n", Refl.Nodes[en.NodeId].Name.c_str(), - EnumTypeToString(en.Type).c_str()); - - DxcHLSLNode node = Refl.Nodes[en.NodeId]; - - for (uint32_t i = 0; i < node.ChildCount; ++i) { - - DxcHLSLNode child = Refl.Nodes[en.NodeId + 1 + i]; - - printf("%u %s = %" PRIi64 "\n", i, child.Name.c_str(), - Refl.EnumValues[child.LocalId].Value); - } - } - - for (DxcHLSLRegister reg : Refl.Registers) { - printf("%s%s : register(%c%u, space%u);\n", - Refl.Nodes[reg.NodeId].Name.c_str(), - RegisterGetArraySize(Refl, reg).c_str(), - RegisterGetSpaceChar(reg), - reg.BindPoint, - reg.Space); - } - - for (DxcHLSLFunction func : Refl.Functions) { - printf("%s (return: %s, hasDefinition: %s, numParams: %u)\n", - Refl.Nodes[func.NodeId].Name.c_str(), - func.HasReturn ? "true" : "false", - func.HasDefinition ? "true" : "false", - func.NumParameters); - } - RecursePrint(Refl, 0, 0); + RecursePrint(Refl, 0, 0, 0); printf("%p\n", &Refl); } From 85b0976a44a57657a845d71b3c369b6d271c52ba Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 27 Aug 2025 20:22:50 +0200 Subject: [PATCH 014/126] Variable is now very minimal, the localId points to the type node and no other data is required. Removed unused data from DxcHLSLType and added logging for a type. A buffer now recurses through members and makes nodes. Now handling printing types and member variables. --- .../clang/tools/libclang/dxcrewriteunused.cpp | 239 +++++++++++++----- 1 file changed, 176 insertions(+), 63 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 66a076453b..f4204ef086 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1288,7 +1288,7 @@ enum class DxcHLSLNodeType : uint64_t { Namespace, Typedef, Using, - Variable, + Variable, //localId points to the type for a variable Parameter, Type }; @@ -1385,8 +1385,7 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and // relatively serializable uint32_t NameId; //Can be empty - std::vector MemberTypes; - std::vector Interfaces; + std::vector MemberTypes; //Member variables (node id to variable) union { struct { @@ -1401,41 +1400,25 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and union { uint32_t ElementsOrArrayId; struct { - uint32_t HasArrayInfo0 : 1; // If 0, indicates that elements represents 1D - // array + uint32_t HasArrayInfo0 : 1; // If 0, 1D array with size of Elements uint32_t Elements : 31; // Number of elements (0 if not an array) }; struct { - uint32_t HasArrayInfo1 : 1; // If 1, indicates that elements represents - // multi dimensional array + uint32_t HasArrayInfo1 : 1; // If 1, nD array at Refl.Arrays[ArrayId] uint32_t ArrayId : 31; // Array id }; }; uint32_t BaseClass; // -1 if none, otherwise a type index - uint32_t SubType; // -1 if none, otherwise a type index bool operator==(const DxcHLSLType &Other) const { return Other.NameId == NameId && Other.MemberTypes == MemberTypes && - Other.Interfaces == Interfaces && ClassTypeRowsColums == Other.ClassTypeRowsColums && ElementsOrArrayId == Other.ElementsOrArrayId && - BaseClass == Other.BaseClass && SubType == Other.SubType; + BaseClass == Other.BaseClass; } -}; - -struct DxcHLSLVariable { // Almost maps to CShaderReflectionVariable and - // D3D12_SHADER_VARIABLE_DESC, but tightly packed and - // easily serializable - uint32_t ConstantBuffer; - uint32_t Type; - uint32_t NameId; // Can be empty - - bool operator==(const DxcHLSLVariable &Other) const { - return Other.ConstantBuffer == ConstantBuffer && Other.Type == Type && - Other.NameId == NameId; - } + DxcHLSLType() = default; }; struct DxcRegisterTypeInfo { @@ -1447,9 +1430,6 @@ struct DxcRegisterTypeInfo { }; struct DxcHLSLBuffer { //Almost maps to CShaderReflectionConstantBuffer and D3D12_SHADER_BUFFER_DESC - - std::vector Variables; - D3D_CBUFFER_TYPE Type; uint32_t NodeId; }; @@ -1477,7 +1457,6 @@ struct DxcReflectionData { std::vector ArraySizes; std::vector Types; - std::vector Variables; std::vector Buffers; }; @@ -2138,7 +2117,11 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, //TODO: Struct recurse - //TODO: Interfaces, base class + (void) type.MemberTypes; + + //TODO: Base class + + type.BaseClass = (uint32_t) -1; assert(Refl.Types.size() < (uint32_t)-1 && "Type id out of bounds"); @@ -2154,51 +2137,35 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, return i; } -std::vector RecurseBuffer(ASTContext &ASTCtx, DxcReflectionData &Refl, - DeclContext *Buffer, uint32_t BufferId, - bool DefaultRowMaj) { - - std::vector variables; +void RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, + DxcReflectionData &Refl, DeclContext *Buffer, + bool DefaultRowMaj, uint32_t ParentId) { for (Decl *decl : Buffer->decls()) { - DxcHLSLVariable variable = {BufferId}; + std::string name; if (NamedDecl *named = dyn_cast(decl)) - variable.NameId = RegisterString(Refl, named->getName()); - - variable.Type = GenerateTypeInfo(ASTCtx, Refl, decl, DefaultRowMaj); - assert(Refl.Variables.size() < (uint32_t)-1 && "Variable id out of bounds"); - - uint32_t i = 0, j = (uint32_t)Refl.Variables.size(); - - for (; i < j; ++i) - if (Refl.Variables[i] == variable) - break; + name = named->getName(); - if (i == j) - Refl.Variables.push_back(variable); + uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, decl, DefaultRowMaj); - variables.push_back(i); + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, decl, + DxcHLSLNodeType::Variable, ParentId, typeId); } - - return variables; } uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcReflectionData &Refl, - DeclContext *Buffer, uint32_t NodeId, - D3D_CBUFFER_TYPE Type, bool DefaultRowMaj) { + const SourceManager &SM, DeclContext *Buffer, + uint32_t NodeId, D3D_CBUFFER_TYPE Type, + bool DefaultRowMaj) { assert(Refl.Buffers.size() < (uint32_t)-1 && "Buffer id out of bounds"); uint32_t bufferId = (uint32_t)Refl.Buffers.size(); - std::vector variables = - RecurseBuffer(ASTCtx, Refl, Buffer, bufferId, DefaultRowMaj); + RecurseBuffer(ASTCtx, SM, Refl, Buffer, DefaultRowMaj, NodeId); - Refl.Buffers.push_back({ - variables, - Type, - NodeId}); + Refl.Buffers.push_back({Type, NodeId}); return bufferId; } @@ -2328,7 +2295,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, CBuffer, DxcHLSLNodeType::Register, ParentNodeId, (uint32_t)Refl.Registers.size()); - uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, CBuffer, nodeId, + uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, SM, CBuffer, nodeId, D3D_CT_CBUFFER, DefaultRowMaj); DxcHLSLRegister regD3D12 = { @@ -2603,7 +2570,7 @@ std::string RegisterGetArraySize(const DxcReflectionData &Refl, const DxcHLSLReg std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { - const char *arr[] = { + static const char *arr[] = { "uint", "int", "uint64_t", "int64_t", "uint16_t", "int16_t", }; @@ -2612,18 +2579,148 @@ std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { std::string NodeTypeToString(DxcHLSLNodeType type) { - const char *arr[] = {"Register", "Function", "Enum", - "EnumValue", "Namespace", "Typedef", "Using", "Variable", - "Parameter", "Type" }; + static const char *arr[] = {"Register", "Function", "Enum", "EnumValue", + "Namespace", "Typedef", "Using", "Variable", + "Parameter", "Type"}; return arr[(int)type]; } +std::string GetBuiltinTypeName(const DxcReflectionData &Refl, + const DxcHLSLType &Type) { + + std::string type; + + if (Type.Class != D3D_SVC_STRUCT) { + + static const char *arr[] = {"void", + "bool", + "int", + "float", + "string", + NULL, + "Texture1D", + "Texture2D", + "Texture3D", + "TextureCube", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "uint", + "uint8_t", + NULL, + NULL, + NULL, + NULL, + "Buffer", + "ConstantBuffer", + NULL, + "Texture1DArray", + "Texture2DArray", + NULL, + NULL, + "Texture2DMS", + "Texture2DMSArray", + "TextureCubeArray", + NULL, + NULL, + NULL, + NULL, + "double", + "RWTexture1D", + "RWTexture1DArray", + "RWTexture2D", + "RWTexture2DArray", + "RWTexture3D", + "RWBuffer", + "ByteAddressBuffer", + "RWByteAddressBuffer", + "StructuredBuffer", + "RWStructuredBuffer", + "AppendStructuredBuffer", + "ConsumeStructuredBuffer", + "min8float", + "min10float", + "min16float", + "min12int", + "min16int", + "min16uint", + "int16_t", + "uint16_t", + "float16_t", + "int64_t", + "uint64_t"}; + + const char *ptr = arr[Type.Type]; + + if (ptr) + type = ptr; + } + + switch (Type.Class) { + + case D3D_SVC_MATRIX_ROWS: + case D3D_SVC_VECTOR: + + type += std::to_string(Type.Columns); + + if (Type.Class == D3D_SVC_MATRIX_ROWS) + type += "x" + std::to_string(Type.Rows); + + break; + + case D3D_SVC_MATRIX_COLUMNS: + type += std::to_string(Type.Rows) + "x" + std::to_string(Type.Columns); + break; + } + + return type; +} + +std::string PrintTypeInfo(const DxcReflectionData &Refl, + const DxcHLSLType &Type, + const std::string &PreviousTypeName) { + + std::string result; + + if (Type.HasArrayInfo1) { + + const DxcHLSLArray &arr = Refl.Arrays[Type.ArrayId]; + + for (uint32_t i = 0; i < arr.ArrayElem; ++i) + result += "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart + i]) + "]"; + + } + + else if (Type.Elements) + result += "[" + std::to_string(Type.Elements) + "]"; + + //Obtain type name (returns empty if it's not a builtin type) + + std::string underlyingTypeName = GetBuiltinTypeName(Refl, Type); + + if (PreviousTypeName != underlyingTypeName) + result += " (" + underlyingTypeName + ")"; + + if (Type.BaseClass != (uint32_t)-1) + result += " : " + Refl.Strings[Refl.Types[Type.BaseClass].NameId]; + + return result; +} + uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, uint32_t Depth, uint32_t IndexInParent) { const DxcHLSLNode &node = Refl.Nodes[NodeId]; + uint32_t typeToPrint = (uint32_t)-1; + if (NodeId) { printf("%s%s %s\n", std::string(Depth - 1, '\t').c_str(), @@ -2644,6 +2741,10 @@ uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, reg.BindPoint, reg.Space); break; } + + case DxcHLSLNodeType::Variable: + typeToPrint = node.LocalId; + break; case DxcHLSLNodeType::Function: { const DxcHLSLFunction &func = Refl.Functions[node.LocalId]; @@ -2670,7 +2771,6 @@ uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, case DxcHLSLNodeType::Type: case DxcHLSLNodeType::Typedef: case DxcHLSLNodeType::Using: - case DxcHLSLNodeType::Variable: case DxcHLSLNodeType::Parameter: break; @@ -2680,6 +2780,19 @@ uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, } } + if (typeToPrint != (uint32_t)-1) { + + const DxcHLSLType &type = Refl.Types[typeToPrint]; + + const std::string &name = Refl.Strings[type.NameId]; + + printf("%s%s%s\n", std::string(Depth, '\t').c_str(), name.c_str(), + PrintTypeInfo(Refl, type, name).c_str()); + + for (uint32_t i = 0; i < type.MemberTypes.size(); ++i) + RecursePrint(Refl, type.MemberTypes[i], Depth + 1, i); + } + for (uint32_t i = 0, j = 0; i < node.ChildCount; ++i, ++j) i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1, j); From 76c33fcfb948e50fa231ebed2fe0f577a2b5d9f0 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 27 Aug 2025 23:46:41 +0200 Subject: [PATCH 015/126] Added struct members and now also going through registers that have buffer information such as StructuredBuffer/ConstantBuffer. --- .../clang/tools/libclang/dxcrewriteunused.cpp | 298 ++++++++++++------ 1 file changed, 199 insertions(+), 99 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index f4204ef086..c10a343fcc 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1380,12 +1380,22 @@ union DxcHLSLArray { } }; +struct DxcHLSLMember { + + uint32_t NameId; + uint32_t TypeId; + + bool operator==(const DxcHLSLMember &Other) const { + return Other.NameId == NameId && Other.TypeId == TypeId; + } +}; + struct DxcHLSLType { // Almost maps to CShaderReflectionType and // D3D12_SHADER_TYPE_DESC, except tightly packed and // relatively serializable uint32_t NameId; //Can be empty - std::vector MemberTypes; //Member variables (node id to variable) + std::vector Members; union { struct { @@ -1412,7 +1422,7 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and uint32_t BaseClass; // -1 if none, otherwise a type index bool operator==(const DxcHLSLType &Other) const { - return Other.NameId == NameId && Other.MemberTypes == MemberTypes && + return Other.NameId == NameId && Other.Members == Members && ClassTypeRowsColums == Other.ClassTypeRowsColums && ElementsOrArrayId == Other.ElementsOrArrayId && BaseClass == Other.BaseClass; @@ -1481,7 +1491,7 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, const LangOptions &LangOpts, const std::string &UnqualifiedName, Decl *Decl, DxcHLSLNodeType Type, uint32_t ParentNodeId, - uint32_t LocalId) { + uint32_t LocalId, const SourceRange *Range = nullptr) { assert(Refl.Nodes.size() < (uint32_t)(1 << 24) && "Nodes overflow"); assert(LocalId < (uint32_t)(1 << 24) && "LocalId overflow"); @@ -1509,7 +1519,9 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, uint16_t fileNameId = (uint16_t)-1; - SourceRange range = Decl->getSourceRange(); + SourceRange range = + Decl ? Decl->getSourceRange() : (Range ? *Range : SourceRange()); + SourceLocation start = range.getBegin(); SourceLocation end = range.getEnd(); @@ -1821,78 +1833,15 @@ static uint32_t PushArray(DxcReflectionData &Refl, uint32_t ArraySizeFlat, return arrayId; } -static void FillReflectionRegisterAt( - const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, - DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, - ValueDecl *ValDesc, const std::vector &ArraySize, - DxcReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId) { - - ArrayRef UA = ValDesc->getUnusualAnnotations(); - - hlsl::RegisterAssignment *reg = nullptr; - - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { - - if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) - continue; - - reg = cast(*It); - } - - assert(reg && "Found a register missing a RegisterAssignment, even though " - "GenerateConsistentBindings should have already generated it"); - - DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); - - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, - DxcHLSLNodeType::Register, ParentNodeId, (uint32_t)Refl.Registers.size()); - - uint32_t arrayId = PushArray(Refl, ArraySizeFlat, ArraySize); - - DxcHLSLRegister regD3D12 = { - - inputType.RegisterType, - reg->RegisterNumber, - ArraySizeFlat, - (uint32_t)inputType.RegisterFlags, - inputType.TextureValue, - inputType.TextureDimension, - inputType.SampleCount, - reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() - : AutoBindingSpace, - nodeId, - arrayId - }; - - Refl.Registers.push_back(regD3D12); -} - -class PrintfStream : public llvm::raw_ostream { -public: - PrintfStream() { SetUnbuffered(); } - -private: - void write_impl(const char *Ptr, size_t Size) override { - printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly - } - - uint64_t current_pos() const override { return 0; } -}; - uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, - Decl *Decl, bool DefaultRowMaj) { - - ValueDecl *valDecl = dyn_cast(Decl); - assert(valDecl && "Decl was expected to be a ValueDecl but wasn't"); + QualType Original, bool DefaultRowMaj) { DxcHLSLType type = {}; - QualType original = valDecl->getType(); // Unwrap array uint32_t arraySize = 1; - QualType underlying = original, forName = original; + QualType underlying = Original, forName = Original; std::vector arrayElem; while (const ConstantArrayType *arr = @@ -1908,7 +1857,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, // Name; Omit struct, class and const keywords - PrintingPolicy policy(valDecl->getASTContext().getLangOpts()); + PrintingPolicy policy(ASTCtx.getLangOpts()); policy.SuppressScope = false; policy.AnonymousTagLocations = false; policy.SuppressTagKeyword = true; @@ -1933,8 +1882,12 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, if (const RecordType *record = underlying->getAs()) { + bool standardType = false; + + RecordDecl *recordDecl = record->getDecl(); + if (const ClassTemplateSpecializationDecl *templateClass = - dyn_cast(record->getDecl())) { + dyn_cast(recordDecl)) { const std::string &name = templateClass->getIdentifier()->getName(); @@ -1964,6 +1917,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, underlying = params[0].getAsType(); type.Columns = params[1].getAsIntegral().getSExtValue(); type.Class = D3D_SVC_VECTOR; + standardType = true; } break; @@ -1983,7 +1937,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, bool isRowMajor = DefaultRowMaj; - HasHLSLMatOrientation(original, &isRowMajor); + HasHLSLMatOrientation(Original, &isRowMajor); if (!isRowMajor) { uint32_t rows = type.Rows; @@ -1993,6 +1947,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, type.Class = isRowMajor ? D3D_SVC_MATRIX_ROWS : D3D_SVC_MATRIX_COLUMNS; + standardType = true; } break; @@ -2030,6 +1985,30 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, // D3D_SVT_APPEND_STRUCTURED_BUFFER = 50, // D3D_SVT_CONSUME_STRUCTURED_BUFFER = 51, } + + // Fill members + + if (!standardType && recordDecl->isCompleteDefinition()) { + + for (Decl *decl : recordDecl->decls()) { + + // TODO: We could query other types VarDecl + + FieldDecl *fieldDecl = dyn_cast(decl); + + if (!fieldDecl) + continue; + + QualType original = fieldDecl->getType(); + std::string name = fieldDecl->getName(); + + uint32_t nameId = RegisterString(Refl, name); + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); + + type.Members.push_back(DxcHLSLMember{nameId, typeId}); + } + } } //Type name @@ -2115,10 +2094,6 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, } } - //TODO: Struct recurse - - (void) type.MemberTypes; - //TODO: Base class type.BaseClass = (uint32_t) -1; @@ -2137,21 +2112,139 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, return i; } +static void FillReflectionRegisterAt( + const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, + DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, + ValueDecl *ValDesc, const std::vector &ArraySize, + DxcReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId, + bool DefaultRowMaj) { + + ArrayRef UA = ValDesc->getUnusualAnnotations(); + + hlsl::RegisterAssignment *reg = nullptr; + + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { + + if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) + continue; + + reg = cast(*It); + } + + assert(reg && "Found a register missing a RegisterAssignment, even though " + "GenerateConsistentBindings should have already generated it"); + + DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, + DxcHLSLNodeType::Register, ParentNodeId, (uint32_t)Refl.Registers.size()); + + uint32_t arrayId = PushArray(Refl, ArraySizeFlat, ArraySize); + + DxcHLSLRegister regD3D12 = { + + inputType.RegisterType, + reg->RegisterNumber, + ArraySizeFlat, + (uint32_t)inputType.RegisterFlags, + inputType.TextureValue, + inputType.TextureDimension, + inputType.SampleCount, + reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() + : AutoBindingSpace, + nodeId, + arrayId}; + + Refl.Registers.push_back(regD3D12); + + bool isListType = true; + + switch (inputType.RegisterType) { + + case D3D_SIT_CBUFFER: + case D3D_SIT_TBUFFER: + isListType = false; + [[fallthrough]]; + + case D3D_SIT_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: { + + const RecordType *recordType = Type->getAs(); + + assert(recordType && "Invalid type (not RecordType)"); + + const ClassTemplateSpecializationDecl *templateDesc = + dyn_cast(recordType->getDecl()); + + assert(templateDesc && "Invalid template type"); + + const ArrayRef ¶ms = + templateDesc->getTemplateArgs().asArray(); + + assert(params.size() == 1 && "Expected Type"); + + QualType innerType = params[0].getAsType(); + + // The name of the inner struct is $Element if 'array', otherwise equal to + // register name + + uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, innerType, DefaultRowMaj); + + SourceRange sourceRange = ValDesc->getSourceRange(); + + uint32_t nestNodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), + isListType ? "$Element" : ValDesc->getName(), nullptr, + DxcHLSLNodeType::Variable, nodeId, typeId, &sourceRange); + + break; + } + } +} + +class PrintfStream : public llvm::raw_ostream { +public: + PrintfStream() { SetUnbuffered(); } + +private: + void write_impl(const char *Ptr, size_t Size) override { + printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly + } + + uint64_t current_pos() const override { return 0; } +}; + +template void RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, - DxcReflectionData &Refl, DeclContext *Buffer, + DxcReflectionData &Refl, const T& Decls, bool DefaultRowMaj, uint32_t ParentId) { - for (Decl *decl : Buffer->decls()) { + for (Decl *decl : Decls) { - std::string name; + ValueDecl *valDecl = dyn_cast(decl); + assert(valDecl && "Decl was expected to be a ValueDecl but wasn't"); + QualType original = valDecl->getType(); - if (NamedDecl *named = dyn_cast(decl)) - name = named->getName(); + std::string name = valDecl->getName(); - uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, decl, DefaultRowMaj); + uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, decl, + uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, decl, DxcHLSLNodeType::Variable, ParentId, typeId); + + //Handle struct recursion + + if (RecordDecl *recordDecl = dyn_cast(decl)) { + + if (!recordDecl->isCompleteDefinition()) + continue; + + RecurseBuffer(ASTCtx, SM, Refl, recordDecl->fields(), DefaultRowMaj, nodeId); + } } } @@ -2163,7 +2256,7 @@ uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcReflectionData &Refl, assert(Refl.Buffers.size() < (uint32_t)-1 && "Buffer id out of bounds"); uint32_t bufferId = (uint32_t)Refl.Buffers.size(); - RecurseBuffer(ASTCtx, SM, Refl, Buffer, DefaultRowMaj, NodeId); + RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), DefaultRowMaj, NodeId); Refl.Buffers.push_back({Type, NodeId}); @@ -2459,7 +2552,8 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, continue; FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, ValDecl, - arrayElem, Refl, AutoBindingSpace, ParentNodeId); + arrayElem, Refl, AutoBindingSpace, ParentNodeId, + DefaultRowMaj); } else if (RecordDecl *RecDecl = dyn_cast(it)) { @@ -2701,11 +2795,11 @@ std::string PrintTypeInfo(const DxcReflectionData &Refl, else if (Type.Elements) result += "[" + std::to_string(Type.Elements) + "]"; - //Obtain type name (returns empty if it's not a builtin type) + // Obtain type name (returns empty if it's not a builtin type) std::string underlyingTypeName = GetBuiltinTypeName(Refl, Type); - if (PreviousTypeName != underlyingTypeName) + if (PreviousTypeName != underlyingTypeName && underlyingTypeName.size()) result += " (" + underlyingTypeName + ")"; if (Type.BaseClass != (uint32_t)-1) @@ -2714,6 +2808,22 @@ std::string PrintTypeInfo(const DxcReflectionData &Refl, return result; } +void RecursePrintType(const DxcReflectionData &Refl, uint32_t TypeId, + uint32_t Depth, const char *Prefix = "") { + + const DxcHLSLType &type = Refl.Types[TypeId]; + + const std::string &name = Refl.Strings[type.NameId]; + + printf("%s%s%s%s\n", std::string(Depth, '\t').c_str(), Prefix, name.c_str(), + PrintTypeInfo(Refl, type, name).c_str()); + + for (uint32_t i = 0; i < type.Members.size(); ++i) { + std::string prefix = Refl.Strings[type.Members[i].NameId] + ": "; + RecursePrintType(Refl, type.Members[i].TypeId, Depth + 1, prefix.c_str()); + } +} + uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, uint32_t Depth, uint32_t IndexInParent) { @@ -2780,18 +2890,8 @@ uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, } } - if (typeToPrint != (uint32_t)-1) { - - const DxcHLSLType &type = Refl.Types[typeToPrint]; - - const std::string &name = Refl.Strings[type.NameId]; - - printf("%s%s%s\n", std::string(Depth, '\t').c_str(), name.c_str(), - PrintTypeInfo(Refl, type, name).c_str()); - - for (uint32_t i = 0; i < type.MemberTypes.size(); ++i) - RecursePrint(Refl, type.MemberTypes[i], Depth + 1, i); - } + if (typeToPrint != (uint32_t)-1) + RecursePrintType(Refl, typeToPrint, Depth); for (uint32_t i = 0, j = 0; i < node.ChildCount; ++i, ++j) i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1, j); From ad65161f988679dc623e894127cf4406907accda Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Thu, 28 Aug 2025 15:45:04 +0200 Subject: [PATCH 016/126] Removal of bit fields to allow consistent writing to disk regardless of compiler & cpu. TODO: Node bitfields and make members of dxc hlsl type flat --- .../clang/tools/libclang/dxcrewriteunused.cpp | 267 +++++++++++------- 1 file changed, 167 insertions(+), 100 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index c10a343fcc..2d5a9fa830 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1341,43 +1341,95 @@ struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC (ex. }; struct DxcHLSLFunction { + uint32_t NodeId; - uint32_t NumParameters : 30; - uint32_t HasReturn : 1; - uint32_t HasDefinition : 1; + uint32_t NumParametersHasReturnAndDefinition; + + DxcHLSLFunction() = default; + + DxcHLSLFunction(uint32_t NodeId, uint32_t NumParameters, bool HasReturn, + bool HasDefinition) + : NumParametersHasReturnAndDefinition(NumParameters | + (HasReturn ? (1 << 30) : 0) | + (HasDefinition ? (1 << 31) : 0)) { + + assert(NumParameters < (1 << 30) && "NumParameters out of bounds"); + } + + uint32_t GetNumParameters() const { + return NumParametersHasReturnAndDefinition << 2 >> 2; + } + + bool HasReturn() const { + return (NumParametersHasReturnAndDefinition >> 30) & 1; + } + + bool HasDefinition() const { + return (NumParametersHasReturnAndDefinition >> 31) & 1; + } }; struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus // the Name (and uID replaced with NodeID) and added - // arrayIndex + // arrayIndex and better packing + + uint8_t Type; // D3D_SHADER_INPUT_TYPE + uint8_t Dimension; // D3D_SRV_DIMENSION + uint8_t ReturnType; // D3D_RESOURCE_RETURN_TYPE + uint8_t uFlags; - D3D_SHADER_INPUT_TYPE Type; // Type of resource (e.g. texture, cbuffer, etc.) - uint32_t BindPoint; // Starting bind point - uint32_t BindCount; // Number of contiguous bind points (for arrays) + uint32_t BindPoint; + uint32_t Space; + uint32_t BindCount; - uint32_t uFlags; // Input binding flags - D3D_RESOURCE_RETURN_TYPE ReturnType; // Return type (if texture) - D3D_SRV_DIMENSION Dimension; // Dimension (if texture) - uint32_t NumSamples; // Number of samples (0 if not MS texture) - uint32_t Space; // Register space + uint32_t NumSamplesOrStride; uint32_t NodeId; - uint32_t ArrayId; // Only accessible if BindCount > 1 and the array is multi - // dimensional - uint32_t BufferId; //If cbuffer or structured buffer + uint32_t ArrayId; // Only if BindCount > 1 and the array is 2D+ + uint32_t BufferId; // If cbuffer or structured buffer + + DxcHLSLRegister() = default; + DxcHLSLRegister(D3D_SHADER_INPUT_TYPE Type, uint32_t BindPoint, + uint32_t BindCount, uint32_t uFlags, + D3D_RESOURCE_RETURN_TYPE ReturnType, + D3D_SRV_DIMENSION Dimension, uint32_t NumSamples, + uint32_t Space, uint32_t NodeId, uint32_t ArrayId, + uint32_t BufferId) + : Type(Type), BindPoint(BindPoint), BindCount(BindCount), uFlags(uFlags), + ReturnType(ReturnType), Dimension(Dimension), + NumSamplesOrStride(NumSamples), Space(Space), NodeId(NodeId), + ArrayId(ArrayId), BufferId(BufferId) { + + assert(Type >= D3D_SIT_CBUFFER && Type <= D3D_SIT_UAV_FEEDBACKTEXTURE && + "Invalid type"); + + assert(ReturnType >= 0 && + ReturnType <= D3D_RETURN_TYPE_CONTINUED && "Invalid return type"); + + assert(Dimension >= D3D_SRV_DIMENSION_UNKNOWN && + Dimension <= D3D_SRV_DIMENSION_BUFFEREX && "Invalid srv dimension"); + + assert(!(uFlags >> 8) && "Invalid user flags"); + } }; -union DxcHLSLArray { +struct DxcHLSLArray { - struct { - uint32_t ArrayElem : 4; // Array of up to 8 deep (like spirv) - uint32_t ArrayStart : 28; // Index into ArraySizes with ArraySize - }; + uint32_t ArrayElemStart; + + DxcHLSLArray() = default; + DxcHLSLArray(uint32_t ArrayElem, uint32_t ArrayStart) + : ArrayElemStart((ArrayElem << 28) | ArrayStart) { - uint32_t Data; + assert(ArrayElem <= 8 && ArrayElem > 1 && "ArrayElem out of bounds"); + assert(ArrayStart < (1 << 28) && "ArrayStart out of bounds"); + } bool operator==(const DxcHLSLArray &Other) const { - return Other.Data == Data; + return Other.ArrayElemStart == ArrayElemStart; } + + uint32_t ArrayElem() const { return ArrayElemStart >> 28; } + uint32_t ArrayStart() const { return ArrayElemStart << 4 >> 4; } }; struct DxcHLSLMember { @@ -1394,31 +1446,21 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and // D3D12_SHADER_TYPE_DESC, except tightly packed and // relatively serializable - uint32_t NameId; //Can be empty std::vector Members; - union { - struct { - D3D_SHADER_VARIABLE_CLASS Class : 8; - D3D_SHADER_VARIABLE_TYPE Type : 8; - uint32_t Rows : 8; - uint32_t Columns : 8; - }; - uint32_t ClassTypeRowsColums; - }; + uint32_t NameId; // Can be empty union { - uint32_t ElementsOrArrayId; - struct { - uint32_t HasArrayInfo0 : 1; // If 0, 1D array with size of Elements - uint32_t Elements : 31; // Number of elements (0 if not an array) - }; struct { - uint32_t HasArrayInfo1 : 1; // If 1, nD array at Refl.Arrays[ArrayId] - uint32_t ArrayId : 31; // Array id + uint8_t Class; // D3D_SHADER_VARIABLE_CLASS + uint8_t Type; // D3D_SHADER_VARIABLE_TYPE + uint8_t Rows; + uint8_t Columns; }; + uint32_t ClassTypeRowsColums; }; + uint32_t ElementsOrArrayId; uint32_t BaseClass; // -1 if none, otherwise a type index bool operator==(const DxcHLSLType &Other) const { @@ -1428,7 +1470,32 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and BaseClass == Other.BaseClass; } + bool IsMultiDimensionalArray() const { return ElementsOrArrayId >> 31; } + bool IsArray() const { return ElementsOrArrayId; } + bool Is1DArray() const { return IsArray() && !IsMultiDimensionalArray(); } + + uint32_t Get1DElements() const { + return IsMultiDimensionalArray() ? 0 : ElementsOrArrayId; + } + + uint32_t GetMultiDimensionalArrayId() const { + return IsMultiDimensionalArray() ? (ElementsOrArrayId << 1 >> 1) + : (uint32_t)-1; + } + DxcHLSLType() = default; + DxcHLSLType(uint32_t NameId, uint32_t BaseClass, uint32_t ElementsOrArrayId, + D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE Type, + uint8_t Rows, uint8_t Columns, + const std::vector &Members) + : Members(Members), NameId(NameId), Class(Class), Type(Type), Rows(Rows), + Columns(Columns), ElementsOrArrayId(ElementsOrArrayId), + BaseClass(BaseClass) { + + assert(Class >= D3D_SVC_SCALAR && Class <= D3D_SVC_INTERFACE_POINTER && + "Invalid class"); + assert(Type >= D3D_SVT_VOID && Type <= D3D_SVT_UINT64 && "Invalid type"); + } }; struct DxcRegisterTypeInfo { @@ -1460,7 +1527,7 @@ struct DxcReflectionData { std::vector Enums; std::vector EnumValues; - std::vector Parameters; + //std::vector Parameters; std::vector Annotations; std::vector Arrays; @@ -1836,8 +1903,6 @@ static uint32_t PushArray(DxcReflectionData &Refl, uint32_t ArraySizeFlat, uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, QualType Original, bool DefaultRowMaj) { - DxcHLSLType type = {}; - // Unwrap array uint32_t arraySize = 1; @@ -1862,23 +1927,21 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, policy.AnonymousTagLocations = false; policy.SuppressTagKeyword = true; - type.NameId = RegisterString(Refl, forName.getLocalUnqualifiedType().getAsString(policy)); - + uint32_t nameId = RegisterString(Refl, forName.getLocalUnqualifiedType().getAsString(policy)); uint32_t arrayId = PushArray(Refl, arraySize, arrayElem); + uint32_t elementsOrArrayId = 0; - if (arrayId != (uint32_t)-1) { - type.HasArrayInfo1 = 1; - type.ArrayId = arrayId; - } + if (arrayId != (uint32_t)-1) + elementsOrArrayId = (1u << 31) | arrayId; - else { - type.HasArrayInfo1 = 0; - type.Elements = arraySize > 1 ? arraySize : 0; - } + else + elementsOrArrayId = arraySize > 1 ? arraySize : 0; //Unwrap vector and matrix - type.Class = D3D_SVC_STRUCT; + D3D_SHADER_VARIABLE_CLASS cls = D3D_SVC_STRUCT; + uint8_t rows = 0, columns = 0; + std::vector members; if (const RecordType *record = underlying->getAs()) { @@ -1908,15 +1971,15 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, if (subs == "or") { - type.Rows = 1; + rows = 1; assert(params.size() == 2 && !params[0].getAsType().isNull() && params[1].getKind() == TemplateArgument::Integral && "Expected vector to be vector"); underlying = params[0].getAsType(); - type.Columns = params[1].getAsIntegral().getSExtValue(); - type.Class = D3D_SVC_VECTOR; + columns = params[1].getAsIntegral().getSExtValue(); + cls = D3D_SVC_VECTOR; standardType = true; } @@ -1932,21 +1995,17 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, "Expected matrix to be matrix"); underlying = params[0].getAsType(); - type.Columns = params[1].getAsIntegral().getSExtValue(); - type.Rows = params[2].getAsIntegral().getSExtValue(); + columns = params[1].getAsIntegral().getSExtValue(); + rows = params[2].getAsIntegral().getSExtValue(); bool isRowMajor = DefaultRowMaj; HasHLSLMatOrientation(Original, &isRowMajor); - if (!isRowMajor) { - uint32_t rows = type.Rows; - type.Rows = type.Columns; - type.Columns = rows; - } + if (!isRowMajor) + std::swap(rows, columns); - type.Class = - isRowMajor ? D3D_SVC_MATRIX_ROWS : D3D_SVC_MATRIX_COLUMNS; + cls = isRowMajor ? D3D_SVC_MATRIX_ROWS : D3D_SVC_MATRIX_COLUMNS; standardType = true; } @@ -2006,86 +2065,88 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); - type.Members.push_back(DxcHLSLMember{nameId, typeId}); + members.push_back(DxcHLSLMember{nameId, typeId}); } } } //Type name + D3D_SHADER_VARIABLE_TYPE type = D3D_SVT_VOID; + if (const BuiltinType *bt = dyn_cast(underlying)) { - if (!type.Rows) - type.Rows = type.Columns = 1; + if (!rows) + rows = columns = 1; - if (type.Class == D3D_SVC_STRUCT) - type.Class = D3D_SVC_SCALAR; + if (cls == D3D_SVC_STRUCT) + cls = D3D_SVC_SCALAR; switch (bt->getKind()) { case BuiltinType::Void: - type.Type = D3D_SVT_VOID; + type = D3D_SVT_VOID; break; case BuiltinType::Min10Float: - type.Type = D3D_SVT_MIN10FLOAT; + type = D3D_SVT_MIN10FLOAT; break; case BuiltinType::Min16Float: - type.Type = D3D_SVT_MIN16FLOAT; + type = D3D_SVT_MIN16FLOAT; break; case BuiltinType::HalfFloat: case BuiltinType::Half: - type.Type = D3D_SVT_FLOAT16; + type = D3D_SVT_FLOAT16; break; case BuiltinType::Short: - type.Type = D3D_SVT_INT16; + type = D3D_SVT_INT16; break; case BuiltinType::Min12Int: - type.Type = D3D_SVT_MIN12INT; + type = D3D_SVT_MIN12INT; break; case BuiltinType::Min16Int: - type.Type = D3D_SVT_MIN16INT; + type = D3D_SVT_MIN16INT; break; case BuiltinType::Min16UInt: - type.Type = D3D_SVT_MIN16UINT; + type = D3D_SVT_MIN16UINT; break; case BuiltinType::UShort: - type.Type = D3D_SVT_UINT16; + type = D3D_SVT_UINT16; break; case BuiltinType::Float: - type.Type = D3D_SVT_FLOAT; + type = D3D_SVT_FLOAT; break; case BuiltinType::Int: - type.Type = D3D_SVT_INT; + type = D3D_SVT_INT; break; case BuiltinType::UInt: - type.Type = D3D_SVT_UINT; + type = D3D_SVT_UINT; break; case BuiltinType::Bool: - type.Type = D3D_SVT_BOOL; + type = D3D_SVT_BOOL; break; case BuiltinType::Double: - type.Type = D3D_SVT_DOUBLE; + type = D3D_SVT_DOUBLE; break; case BuiltinType::ULongLong: - type.Type = D3D_SVT_UINT64; + type = D3D_SVT_UINT64; break; case BuiltinType::LongLong: - type.Type = D3D_SVT_INT64; + type = D3D_SVT_INT64; break; default: @@ -2096,18 +2157,21 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, //TODO: Base class - type.BaseClass = (uint32_t) -1; + uint32_t baseClass = (uint32_t) -1; assert(Refl.Types.size() < (uint32_t)-1 && "Type id out of bounds"); + DxcHLSLType hlslType(nameId, baseClass, elementsOrArrayId, cls, type, rows, + columns, members); + uint32_t i = 0, j = (uint32_t)Refl.Types.size(); for (; i < j; ++i) - if (Refl.Types[i] == type) + if (Refl.Types[i] == hlslType) break; if (i == j) - Refl.Types.push_back(type); + Refl.Types.push_back(hlslType); return i; } @@ -2154,7 +2218,9 @@ static void FillReflectionRegisterAt( reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() : AutoBindingSpace, nodeId, - arrayId}; + arrayId, + 0 + }; Refl.Registers.push_back(regD3D12); @@ -2653,8 +2719,8 @@ std::string RegisterGetArraySize(const DxcReflectionData &Refl, const DxcHLSLReg DxcHLSLArray arr = Refl.Arrays[reg.ArrayId]; std::string str; - for (uint32_t i = 0; i < arr.ArrayElem; ++i) - str += "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart + i]) + "]"; + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) + str += "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart() + i]) + "]"; return str; } @@ -2783,17 +2849,18 @@ std::string PrintTypeInfo(const DxcReflectionData &Refl, std::string result; - if (Type.HasArrayInfo1) { + if (Type.IsMultiDimensionalArray()) { - const DxcHLSLArray &arr = Refl.Arrays[Type.ArrayId]; + const DxcHLSLArray &arr = Refl.Arrays[Type.GetMultiDimensionalArrayId()]; - for (uint32_t i = 0; i < arr.ArrayElem; ++i) - result += "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart + i]) + "]"; + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) + result += + "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart() + i]) + "]"; } - else if (Type.Elements) - result += "[" + std::to_string(Type.Elements) + "]"; + else if (Type.IsArray()) + result += "[" + std::to_string(Type.Get1DElements()) + "]"; // Obtain type name (returns empty if it's not a builtin type) @@ -2860,8 +2927,8 @@ uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, const DxcHLSLFunction &func = Refl.Functions[node.LocalId]; printf("%sreturn: %s, hasDefinition: %s, numParams: %u\n", std::string(Depth, '\t').c_str(), - func.HasReturn ? "true" : "false", - func.HasDefinition ? "true" : "false", func.NumParameters); + func.HasReturn() ? "true" : "false", + func.HasDefinition() ? "true" : "false", func.GetNumParameters()); break; } From 18b14ca6761493d5c50a93bc8e2705d460d3a785 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Thu, 28 Aug 2025 17:56:30 +0200 Subject: [PATCH 017/126] Flattened DxcHLSLType by adding a DxcHLSLMember array to DxcReflectionData --- .../clang/tools/libclang/dxcrewriteunused.cpp | 69 ++++++++++++------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 2d5a9fa830..f4ebcbadca 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1443,31 +1443,39 @@ struct DxcHLSLMember { }; struct DxcHLSLType { // Almost maps to CShaderReflectionType and - // D3D12_SHADER_TYPE_DESC, except tightly packed and - // relatively serializable - - std::vector Members; - - uint32_t NameId; // Can be empty + // D3D12_SHADER_TYPE_DESC, but tightly packed and + // easily serializable + union { + struct { + uint32_t MembersCount; + uint32_t MembersStart; + }; + uint64_t MembersData; + }; union { struct { - uint8_t Class; // D3D_SHADER_VARIABLE_CLASS - uint8_t Type; // D3D_SHADER_VARIABLE_TYPE + uint32_t NameId; // Can be empty + uint8_t Class; // D3D_SHADER_VARIABLE_CLASS + uint8_t Type; // D3D_SHADER_VARIABLE_TYPE uint8_t Rows; uint8_t Columns; }; - uint32_t ClassTypeRowsColums; + uint64_t NameIdClassTypeRowsColums; }; - uint32_t ElementsOrArrayId; - uint32_t BaseClass; // -1 if none, otherwise a type index + union { + struct { + uint32_t ElementsOrArrayId; + uint32_t BaseClass; // -1 if none, otherwise a type index + }; + uint64_t ElementsOrArrayIdBaseClass; + }; bool operator==(const DxcHLSLType &Other) const { - return Other.NameId == NameId && Other.Members == Members && - ClassTypeRowsColums == Other.ClassTypeRowsColums && - ElementsOrArrayId == Other.ElementsOrArrayId && - BaseClass == Other.BaseClass; + return Other.MembersData == MembersData && + NameIdClassTypeRowsColums == Other.NameIdClassTypeRowsColums && + ElementsOrArrayIdBaseClass == Other.ElementsOrArrayIdBaseClass; } bool IsMultiDimensionalArray() const { return ElementsOrArrayId >> 31; } @@ -1486,11 +1494,11 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and DxcHLSLType() = default; DxcHLSLType(uint32_t NameId, uint32_t BaseClass, uint32_t ElementsOrArrayId, D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE Type, - uint8_t Rows, uint8_t Columns, - const std::vector &Members) - : Members(Members), NameId(NameId), Class(Class), Type(Type), Rows(Rows), - Columns(Columns), ElementsOrArrayId(ElementsOrArrayId), - BaseClass(BaseClass) { + uint8_t Rows, uint8_t Columns, uint32_t MembersCount, + uint32_t MembersStart) + : MembersStart(MembersStart), MembersCount(MembersCount), NameId(NameId), + Class(Class), Type(Type), Rows(Rows), Columns(Columns), + ElementsOrArrayId(ElementsOrArrayId), BaseClass(BaseClass) { assert(Class >= D3D_SVC_SCALAR && Class <= D3D_SVC_INTERFACE_POINTER && "Invalid class"); @@ -1533,6 +1541,7 @@ struct DxcReflectionData { std::vector Arrays; std::vector ArraySizes; + std::vector Members; std::vector Types; std::vector Buffers; }; @@ -1941,7 +1950,9 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, D3D_SHADER_VARIABLE_CLASS cls = D3D_SVC_STRUCT; uint8_t rows = 0, columns = 0; - std::vector members; + + uint32_t membersCount = 0; + uint32_t membersOffset = 0; if (const RecordType *record = underlying->getAs()) { @@ -2065,7 +2076,12 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); - members.push_back(DxcHLSLMember{nameId, typeId}); + if (!membersCount) + membersOffset = (uint32_t) Refl.Members.size(); + + assert(Refl.Members.size() <= (uint32_t)-1 && "Members out of bounds"); + Refl.Members.push_back(DxcHLSLMember{nameId, typeId}); + ++membersCount; } } } @@ -2162,7 +2178,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, assert(Refl.Types.size() < (uint32_t)-1 && "Type id out of bounds"); DxcHLSLType hlslType(nameId, baseClass, elementsOrArrayId, cls, type, rows, - columns, members); + columns, membersCount, membersOffset); uint32_t i = 0, j = (uint32_t)Refl.Types.size(); @@ -2885,9 +2901,10 @@ void RecursePrintType(const DxcReflectionData &Refl, uint32_t TypeId, printf("%s%s%s%s\n", std::string(Depth, '\t').c_str(), Prefix, name.c_str(), PrintTypeInfo(Refl, type, name).c_str()); - for (uint32_t i = 0; i < type.Members.size(); ++i) { - std::string prefix = Refl.Strings[type.Members[i].NameId] + ": "; - RecursePrintType(Refl, type.Members[i].TypeId, Depth + 1, prefix.c_str()); + for (uint32_t i = 0; i < type.MembersCount; ++i) { + const DxcHLSLMember &member = Refl.Members[type.MembersStart + i]; + std::string prefix = Refl.Strings[member.NameId] + ": "; + RecursePrintType(Refl, member.TypeId, Depth + 1, prefix.c_str()); } } From fcd066658f1a94331a322005b99f84b40a331ddd Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Thu, 28 Aug 2025 22:16:27 +0200 Subject: [PATCH 018/126] DxcHLSLNode doesn't use bit fields anymore. Implemented operator== almost everywhere for testing purposes. Added helpers for (de)serializing data. Added serialize/deserialize for DxcReflectionData to ensure a buffer can be output from the rewriter and can be loaded through the utility. --- .../clang/tools/libclang/dxcrewriteunused.cpp | 531 ++++++++++++++++-- 1 file changed, 473 insertions(+), 58 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index f4ebcbadca..5f712c1c98 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1290,38 +1290,160 @@ enum class DxcHLSLNodeType : uint64_t { Using, Variable, //localId points to the type for a variable Parameter, - Type + Type, + + Start = Register, + End = Type }; struct DxcHLSLNode { - uint32_t NameId; // Local name (not including parent's name) - uint32_t SourceScopeInfo; // TODO: + union { + struct { + uint32_t NameId; // Local name (not including parent's name) + + uint16_t FileNameId; + uint16_t SourceLineCount; + }; + uint64_t NameIdFileNameIdSourceLineCount; + }; + + uint64_t LocalIdAnnotationSourceLineStart; + + uint64_t TypeChildsParentAnnotationsSourceColumnHi; + + union { + struct { + uint16_t SourceColumnStartLo; + uint16_t SourceColumnEndLo; + uint32_t Padding; + }; + uint64_t SourceColumnStartEndLo; + }; + + DxcHLSLNode() = default; + + DxcHLSLNode(uint32_t NameId, + + DxcHLSLNodeType NodeType, uint32_t LocalId, + uint32_t AnnotationStart, uint16_t FileNameId, + + uint32_t ChildCount, uint32_t ParentId, uint16_t SourceLineCount, + + uint32_t SourceLineStart, uint32_t SourceColumnStart, + uint32_t SourceColumnEnd, uint16_t AnnotationCount) + : NameId(NameId), FileNameId(FileNameId), + SourceLineCount(SourceLineCount), + SourceColumnStartLo(uint16_t(SourceColumnStart)), + SourceColumnEndLo(uint16_t(SourceColumnEnd)), + LocalIdAnnotationSourceLineStart((uint64_t(LocalId) << (64 - 24)) | + (uint64_t(AnnotationStart) << 20) | + SourceLineStart), + TypeChildsParentAnnotationsSourceColumnHi((uint64_t(NodeType) << 60) | + (uint64_t(ChildCount) << (10 + 2 + 24)) | + (uint64_t(AnnotationCount) << (2 + 24)) | + (SourceColumnStart >> 16 << 24) | + (SourceColumnEnd >> 16 << 25) | + (ParentId)) { + + assert(NodeType >= DxcHLSLNodeType::Start && + NodeType <= DxcHLSLNodeType::End && "Invalid enum value"); + + assert(LocalId < ((1 << 24) - 1) && "LocalId out of bounds"); + assert(ParentId < ((1 << 24) - 1) && "ParentId out of bounds"); + assert(ChildCount < ((1 << 24) - 1) && "ChildCount out of bounds"); + assert(SourceColumnStart < (1 << 17) && "SourceColumnStart out of bounds"); + assert(SourceColumnEnd < (1 << 17) && "SourceColumnEnd out of bounds"); + assert(AnnotationCount < (1 << 10) && "AnnotationCount out of bounds"); + + assert(AnnotationStart < ((1 << 20) - 1) && + "AnnotationStart out of bounds"); - DxcHLSLNodeType NodeType : 4; - uint64_t LocalId : 24; // For example if Enum, maps into Enums[LocalId] - uint64_t AnnotationStart : 20; - uint64_t FileNameId : 16; // Index into Sources; 65535 == None + assert(SourceLineStart < ((1 << 20) - 1) && + "SourceLineStart out of bounds"); + } + + // For example if Enum, maps into Enums[LocalId] + uint32_t GetLocalId() const { + return LocalIdAnnotationSourceLineStart >> (64 - 24); + } - uint64_t ChildCount : 24; // Children start at next node. childCount includes - // recursive children - uint64_t ParentId : 24; - uint64_t SourceLineCount : 16; + uint32_t GetAnnotationStart() const { + return uint32_t(LocalIdAnnotationSourceLineStart << 24 >> (64 - 20)); + } + + uint32_t GetSourceLineStart() const { + return uint32_t(LocalIdAnnotationSourceLineStart & ((1 << 20) - 1)); + } - uint64_t SourceLineStart : 20; // U20_MAX = No source range - uint64_t SourceColumnStart : 17; - uint64_t SourceColumnEnd : 17; - uint64_t AnnotationCount : 10; + DxcHLSLNodeType GetNodeType() const { + return DxcHLSLNodeType(TypeChildsParentAnnotationsSourceColumnHi >> 60); + } + + // Includes recursive children + uint32_t GetChildCount() const { + return uint32_t(TypeChildsParentAnnotationsSourceColumnHi << 4 >> + (64 - 24)); + } + + uint32_t GetAnnotationCount() const { + return uint32_t(TypeChildsParentAnnotationsSourceColumnHi << (4 + 24) >> + (64 - 10)); + } + + uint32_t GetParentId() const { + return uint32_t(TypeChildsParentAnnotationsSourceColumnHi & + ((1 << 24) - 1)); + } + + uint32_t GetSourceColumnStart() const { + return SourceColumnStartLo | + ((TypeChildsParentAnnotationsSourceColumnHi & (1 << 24)) >> + (24 - 16)); + } + + uint32_t GetSourceColumnEnd() const { + return SourceColumnEndLo | + ((TypeChildsParentAnnotationsSourceColumnHi & (1 << 25)) >> + (25 - 16)); + } + + void IncreaseChildCount() { + uint32_t childCount = GetChildCount(); + assert(childCount < ((1 << 24) - 1) && "Child count out of bounds"); + TypeChildsParentAnnotationsSourceColumnHi += uint64_t(1) << (10 + 2 + 24); + } + + bool operator==(const DxcHLSLNode &other) const { + return NameIdFileNameIdSourceLineCount == + other.NameIdFileNameIdSourceLineCount && + SourceColumnStartEndLo == other.SourceColumnStartEndLo && + TypeChildsParentAnnotationsSourceColumnHi == + other.TypeChildsParentAnnotationsSourceColumnHi && + LocalIdAnnotationSourceLineStart == + other.LocalIdAnnotationSourceLineStart; + } }; struct DxcHLSLEnumDesc { + uint32_t NodeId; D3D12_HLSL_ENUM_TYPE Type; + + bool operator==(const DxcHLSLEnumDesc &other) const { + return NodeId == other.NodeId && Type == other.Type; + } }; struct DxcHLSLEnumValue { + int64_t Value; uint32_t NodeId; + + bool operator==(const DxcHLSLEnumValue &other) const { + return Value == other.Value && + NodeId == other.NodeId; + } }; struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC (ex. @@ -1367,25 +1489,53 @@ struct DxcHLSLFunction { bool HasDefinition() const { return (NumParametersHasReturnAndDefinition >> 31) & 1; } + + bool operator==(const DxcHLSLFunction &other) const { + return NodeId == other.NodeId && + NumParametersHasReturnAndDefinition == + other.NumParametersHasReturnAndDefinition; + } }; struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus // the Name (and uID replaced with NodeID) and added // arrayIndex and better packing - uint8_t Type; // D3D_SHADER_INPUT_TYPE - uint8_t Dimension; // D3D_SRV_DIMENSION - uint8_t ReturnType; // D3D_RESOURCE_RETURN_TYPE - uint8_t uFlags; + union { + struct { + uint8_t Type; // D3D_SHADER_INPUT_TYPE + uint8_t Dimension; // D3D_SRV_DIMENSION + uint8_t ReturnType; // D3D_RESOURCE_RETURN_TYPE + uint8_t uFlags; - uint32_t BindPoint; - uint32_t Space; - uint32_t BindCount; + uint32_t BindPoint; + }; + uint64_t TypeDimensionReturnTypeFlagsBindPoint; + }; - uint32_t NumSamplesOrStride; - uint32_t NodeId; - uint32_t ArrayId; // Only if BindCount > 1 and the array is 2D+ - uint32_t BufferId; // If cbuffer or structured buffer + union { + struct { + uint32_t Space; + uint32_t BindCount; + }; + uint64_t SpaceBindCount; + }; + + union { + struct { + uint32_t NumSamplesOrStride; + uint32_t NodeId; + }; + uint64_t NumSamplesOrStrideNodeId; + }; + + union { + struct { + uint32_t ArrayId; // Only if BindCount > 1 and the array is 2D+ + uint32_t BufferId; // If cbuffer or structured buffer + }; + uint64_t ArrayIdBufferId; + }; DxcHLSLRegister() = default; DxcHLSLRegister(D3D_SHADER_INPUT_TYPE Type, uint32_t BindPoint, @@ -1402,14 +1552,22 @@ struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus assert(Type >= D3D_SIT_CBUFFER && Type <= D3D_SIT_UAV_FEEDBACKTEXTURE && "Invalid type"); - assert(ReturnType >= 0 && - ReturnType <= D3D_RETURN_TYPE_CONTINUED && "Invalid return type"); + assert(ReturnType >= 0 && ReturnType <= D3D_RETURN_TYPE_CONTINUED && + "Invalid return type"); assert(Dimension >= D3D_SRV_DIMENSION_UNKNOWN && Dimension <= D3D_SRV_DIMENSION_BUFFEREX && "Invalid srv dimension"); assert(!(uFlags >> 8) && "Invalid user flags"); } + + bool operator==(const DxcHLSLRegister &other) const { + return TypeDimensionReturnTypeFlagsBindPoint == + other.TypeDimensionReturnTypeFlagsBindPoint && + SpaceBindCount == other.SpaceBindCount && + NumSamplesOrStrideNodeId == other.NumSamplesOrStrideNodeId && + ArrayIdBufferId == other.ArrayIdBufferId; + } }; struct DxcHLSLArray { @@ -1514,9 +1672,15 @@ struct DxcRegisterTypeInfo { uint32_t SampleCount; }; -struct DxcHLSLBuffer { //Almost maps to CShaderReflectionConstantBuffer and D3D12_SHADER_BUFFER_DESC +struct DxcHLSLBuffer { // Almost maps to CShaderReflectionConstantBuffer and + // D3D12_SHADER_BUFFER_DESC + D3D_CBUFFER_TYPE Type; uint32_t NodeId; + + bool operator==(const DxcHLSLBuffer &other) const { + return Type == other.Type && NodeId == other.NodeId; + } }; struct DxcReflectionData { @@ -1544,12 +1708,28 @@ struct DxcReflectionData { std::vector Members; std::vector Types; std::vector Buffers; + + void Dump(std::vector &Bytes) const; + + DxcReflectionData() = default; + DxcReflectionData(const std::vector &Bytes); + + bool operator==(const DxcReflectionData& other) const { + return Strings == other.Strings && Sources == other.Sources && + Nodes == other.Nodes && Registers == other.Registers && + Functions == other.Functions && Enums == other.Enums && + EnumValues == other.EnumValues && Annotations == other.Annotations && + Arrays == other.Arrays && ArraySizes == other.ArraySizes && + Members == other.Members && Types == other.Types && + Buffers == other.Buffers; + } }; static uint32_t RegisterString(DxcReflectionData &Refl, const std::string &Name) { assert(Refl.Strings.size() < (uint32_t)-1 && "Strings overflow"); + assert(Name.size() < 32768 && "Strings are limited to 32767"); auto it = Refl.StringsToId.find(Name); @@ -1575,7 +1755,7 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, uint32_t nodeId = Refl.Nodes.size(); uint32_t annotationStart = (uint32_t) Refl.Annotations.size(); - uint32_t annotationCount = 0; + uint16_t annotationCount = 0; if (Decl) { for (const Attr *attr : Decl->attrs()) { @@ -1583,13 +1763,15 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); Refl.Annotations.push_back( RegisterString(Refl, annotate->getAnnotation().str())); + assert(annotationCount != uint16_t(-1) && + "Annotation count out of bounds"); ++annotationCount; } } } - uint32_t sourceLineCount = 0; - uint32_t sourceLineStart = (1 << 20) - 1; + uint16_t sourceLineCount = 0; + uint32_t sourceLineStart = 0; uint32_t sourceColumnStart = 0; uint32_t sourceColumnEnd = 0; @@ -1642,7 +1824,7 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, assert(startCol < 131072 && "Column start is limited to 17-bit"); assert(endCol < 131072 && "Column end is limited to 17-bit"); - sourceLineCount = endLine - startLine + 1; + sourceLineCount = uint16_t(endLine - startLine + 1); sourceLineStart = startLine; sourceColumnStart = startCol; sourceColumnEnd = endCol; @@ -1652,7 +1834,7 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, uint32_t nameId = RegisterString(Refl, UnqualifiedName); - Refl.Nodes.push_back({nameId, 0, Type, LocalId, annotationStart, fileNameId, + Refl.Nodes.push_back(DxcHLSLNode{nameId, Type, LocalId, annotationStart, fileNameId, 0, ParentNodeId, sourceLineCount, sourceLineStart, sourceColumnStart, sourceColumnEnd, annotationCount}); @@ -1660,11 +1842,11 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, while (parentParent != 0) { DxcHLSLNode &parent = Refl.Nodes[parentParent]; - ++parent.ChildCount; - parentParent = parent.ParentId; + parent.IncreaseChildCount(); + parentParent = parent.GetParentId(); } - ++Refl.Nodes[0].ChildCount; + Refl.Nodes[0].IncreaseChildCount(); return nodeId; } @@ -2431,8 +2613,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, // Traverse AST to grab reflection data - //TODO: Niels, Annotations, sources, scopes (if/switch/for/empty scope), nodes for tooling, - // flags for determining how heavy reflection should be (e.g. -reflect_hlsl = -reflect_hlsl_registers -reflect_hlsl_cbuffer -reflect_ + //TODO: Niels, scopes (if/switch/for/empty scope) for (Decl *it : Ctx.decls()) { @@ -2675,13 +2856,8 @@ static void ReflectHLSL(ASTHelper &astHelper, DxcReflectionData& Refl, Refl.Strings.push_back(""); Refl.StringsToId[""] = 0; - Refl.Nodes.push_back({ - 0, 0, - DxcHLSLNodeType::Namespace, - 0, - 0, - 0xFFFF - }); + Refl.Nodes.push_back(DxcHLSLNode{0, DxcHLSLNodeType::Namespace, 0, 0, 0, 0, + 0xFFFF, 0, 0, 0, 0, 0}); RecursiveReflectHLSL(Ctx, astHelper.compiler.getASTContext(), Diags, SM, Refl, AutoBindingSpace, 0, ReflectMask, 0, DefaultRowMaj); @@ -2918,17 +3094,20 @@ uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, if (NodeId) { printf("%s%s %s\n", std::string(Depth - 1, '\t').c_str(), - NodeTypeToString(node.NodeType).c_str(), + NodeTypeToString(node.GetNodeType()).c_str(), Refl.Strings[node.NameId].c_str()); - for (uint32_t i = 0; i < node.AnnotationCount; ++i) + for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) printf("%s[[%s]]\n", std::string(Depth, '\t').c_str(), - Refl.Strings[Refl.Annotations[i]].c_str()); + Refl.Strings[Refl.Annotations[node.GetAnnotationStart() + i]] + .c_str()); - switch (node.NodeType) { + uint32_t localId = node.GetLocalId(); + + switch (node.GetNodeType()) { case DxcHLSLNodeType::Register: { - const DxcHLSLRegister ® = Refl.Registers[node.LocalId]; + const DxcHLSLRegister ® = Refl.Registers[localId]; printf("%s%s : register(%c%u, space%u);\n", std::string(Depth, '\t').c_str(), RegisterGetArraySize(Refl, reg).c_str(), RegisterGetSpaceChar(reg), @@ -2937,11 +3116,11 @@ uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, } case DxcHLSLNodeType::Variable: - typeToPrint = node.LocalId; + typeToPrint = localId; break; case DxcHLSLNodeType::Function: { - const DxcHLSLFunction &func = Refl.Functions[node.LocalId]; + const DxcHLSLFunction &func = Refl.Functions[localId]; printf("%sreturn: %s, hasDefinition: %s, numParams: %u\n", std::string(Depth, '\t').c_str(), func.HasReturn() ? "true" : "false", @@ -2952,12 +3131,12 @@ uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, case DxcHLSLNodeType::Enum: printf("%s: %s\n", std::string(Depth, '\t').c_str(), - EnumTypeToString(Refl.Enums[node.LocalId].Type).c_str()); + EnumTypeToString(Refl.Enums[localId].Type).c_str()); break; case DxcHLSLNodeType::EnumValue: { printf("%s#%u = %" PRIi64 "\n", std::string(Depth, '\t').c_str(), - IndexInParent, Refl.EnumValues[node.LocalId].Value); + IndexInParent, Refl.EnumValues[localId].Value); break; } @@ -2977,12 +3156,241 @@ uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, if (typeToPrint != (uint32_t)-1) RecursePrintType(Refl, typeToPrint, Depth); - for (uint32_t i = 0, j = 0; i < node.ChildCount; ++i, ++j) + for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1, j); - return node.ChildCount; + return node.GetChildCount(); } +struct DxcHLSLHeader { + + uint32_t MagicNumber; + uint16_t Version; + uint16_t Sources; + + uint32_t Strings; + uint32_t Nodes; + + uint32_t Registers; + uint32_t Functions; + + uint32_t Enums; + uint32_t EnumValues; + + uint32_t Annotations; + uint32_t Arrays; + + uint32_t ArraySizes; + uint32_t Members; + + uint32_t Types; + uint32_t Buffers; +}; + +template +T &UnsafeCast(std::vector &Bytes, uint64_t Offset) { + return *(T *)(Bytes.data() + Offset); +} + +template +const T &UnsafeCast(const std::vector &Bytes, uint64_t Offset) { + return *(const T *)(Bytes.data() + Offset); +} + +template +void SkipPadding(uint64_t& Offset) { + Offset = (Offset + alignof(T) - 1) / alignof(T) * alignof(T); +} + +template +void Skip(uint64_t& Offset, const std::vector& Vec) { + Offset += Vec.size() * sizeof(T); +} + +template +void Advance(uint64_t& Offset, const std::vector& Vec) { + SkipPadding(Offset); + Skip(Offset, Vec); +} + +template <> +void Advance(uint64_t &Offset, + const std::vector &Vec) { + for (const std::string &str : Vec) { + Offset += str.size() >= 128 ? 2 : 1; + Offset += str.size(); + } +} + +template +void Advance(uint64_t& Offset, const std::vector& Vec, const std::vector& Vec2, args... arg) { + Advance(Offset, Vec); + Advance(Offset, Vec2, arg...); +} + +template +void Append(std::vector &Bytes, uint64_t &Offset, + const std::vector &Vec) { + static_assert(std::is_pod_v, "Append only works on POD types"); + SkipPadding(Offset); + std::memcpy(&UnsafeCast(Bytes, Offset), Vec.data(), + Vec.size() * sizeof(T)); + Skip(Offset, Vec); +} + +template <> +void Append(std::vector &Bytes, uint64_t &Offset, + const std::vector &Vec) { + + for (const std::string &str : Vec) { + + if (str.size() >= 128) { + UnsafeCast(Bytes, Offset++) = + (uint8_t)(str.size() & 0x7F) | 0x80; + UnsafeCast(Bytes, Offset++) = (uint8_t)(str.size() >> 7); + } + + else + UnsafeCast(Bytes, Offset++) = (uint8_t)str.size(); + + std::memcpy(&UnsafeCast(Bytes, Offset), str.data(), str.size()); + Offset += str.size(); + } +} + +template +void Append(std::vector &Bytes, uint64_t &Offset, + const std::vector &Vec, const std::vector &Vec2, + args... arg) { + Append(Bytes, Offset, Vec); + Append(Bytes, Offset, Vec2, arg...); +} + +template >> +void Consume(const std::vector &Bytes, uint64_t &Offset, T &t) { + + static_assert(std::is_pod_v, "Consume only works on POD types"); + + SkipPadding(Offset); + + if (Offset + sizeof(T) > Bytes.size()) + throw std::out_of_range("Couldn't consume; out of bounds!"); + + std::memcpy(&t, &UnsafeCast(Bytes, Offset), sizeof(T)); + Offset += sizeof(T); +} + +template +void Consume(const std::vector &Bytes, uint64_t &Offset, T *target, + uint64_t Len) { + + static_assert(std::is_pod_v, "Consume only works on POD types"); + + SkipPadding(Offset); + + if (Offset + sizeof(T) * Len > Bytes.size()) + throw std::out_of_range("Couldn't consume; out of bounds!"); + + std::memcpy(target, &UnsafeCast(Bytes, Offset), sizeof(T) * Len); + Offset += sizeof(T) * Len; +} + +template +void Consume(const std::vector &Bytes, uint64_t &Offset, + std::vector &Vec, uint64_t Len) { + Vec.resize(Len); + Consume(Bytes, Offset, Vec.data(), Len); +} + +template <> +void Consume(const std::vector &Bytes, uint64_t &Offset, + std::vector &Vec, uint64_t Len) { + Vec.resize(Len); + + for (uint64_t i = 0; i < Len; ++i) { + + if (Offset >= Bytes.size()) + throw std::out_of_range("Couldn't consume string len; out of bounds!"); + + uint16_t ourLen = uint8_t(Bytes.at(Offset++)); + + if (ourLen >> 7) { + + if (Offset >= Bytes.size()) + throw std::out_of_range("Couldn't consume string len; out of bounds!"); + + ourLen &= ~(1 << 7); + ourLen |= uint16_t(Bytes.at(Offset++)) << 7; + } + + if (Offset + ourLen > Bytes.size()) + throw std::out_of_range("Couldn't consume string len; out of bounds!"); + + Vec[i].resize(ourLen); + std::memcpy(Vec[i].data(), Bytes.data() + Offset, ourLen); + Offset += ourLen; + } +} + +template +void Consume(const std::vector &Bytes, uint64_t &Offset, + std::vector &Vec, uint64_t Len, std::vector &Vec2, + uint64_t Len2, args&... arg) { + Consume(Bytes, Offset, Vec, Len); + Consume(Bytes, Offset, Vec2, Len2, arg...); +} + +static constexpr uint32_t DxcReflectionDataMagic = DXC_FOURCC('D', 'H', 'R', 'D'); +static constexpr uint16_t DxcReflectionDataVersion = 0; + +void DxcReflectionData::Dump(std::vector &Bytes) const { + + uint64_t toReserve = sizeof(DxcHLSLHeader); + + Advance(toReserve, Strings, Sources, Nodes, Registers, Functions, Enums, + EnumValues, Annotations, ArraySizes, Members, Types, Buffers); + + Bytes.resize(toReserve); + + toReserve = 0; + + UnsafeCast(Bytes, toReserve) = { + DxcReflectionDataMagic, DxcReflectionDataVersion, + uint16_t(Sources.size()), uint32_t(Strings.size()), + uint32_t(Nodes.size()), uint32_t(Registers.size()), + uint32_t(Functions.size()), uint32_t(Enums.size()), + uint32_t(EnumValues.size()), uint32_t(Annotations.size()), + uint32_t(Arrays.size()), uint32_t(ArraySizes.size()), + uint32_t(Members.size()), uint32_t(Types.size()), + uint32_t(Buffers.size())}; + + toReserve += sizeof(DxcHLSLHeader); + + Append(Bytes, toReserve, Strings, Sources, Nodes, Registers, Functions, Enums, EnumValues, Annotations, + ArraySizes, Members, Types, Buffers); +} + +DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { + + uint64_t off = 0; + DxcHLSLHeader header; + Consume(Bytes, off, header); + + if (header.MagicNumber != DxcReflectionDataMagic) + throw std::invalid_argument("Invalid magic number"); + + if (header.Version != DxcReflectionDataVersion) + throw std::invalid_argument("Unrecognized version number"); + + Consume(Bytes, off, Strings, header.Strings, Sources, header.Sources, Nodes, header.Nodes, Registers, + header.Registers, Functions, header.Functions, Enums, header.Enums, + EnumValues, header.EnumValues, Annotations, header.Annotations, ArraySizes, header.ArraySizes, Members, + header.Members, Types, header.Types, Buffers, header.Buffers); + + //TODO: Run validation!!! + +}; + static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, ASTUnit::RemappedFile *pRemap, hlsl::options::DxcOpts &opts, @@ -3031,7 +3439,14 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, RecursePrint(Refl, 0, 0, 0); - printf("%p\n", &Refl); + std::vector bytes; + Refl.Dump(bytes); + + DxcReflectionData Deserialized(bytes); + + assert(Deserialized == Refl && "Dump or Deserialize doesn't match"); + + printf("Reflection size: %" PRIu64 "\n", bytes.size()); } if (opts.RWOpt.SkipStatic && opts.RWOpt.SkipFunctionBody) { From 49a70317e36f5031a774b247ba4c8ba456c929dc Mon Sep 17 00:00:00 2001 From: NielsbishereAlt Date: Sat, 30 Aug 2025 16:18:58 +0200 Subject: [PATCH 019/126] Registers now add buffer information if relevant. Added some validation to DxcReflectionData with buffer (deserialize). --- include/dxc/dxctools.h | 6 +- .../clang/tools/libclang/dxcrewriteunused.cpp | 187 +++++++++++++++++- 2 files changed, 187 insertions(+), 6 deletions(-) diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 7394d1b094..af2f746256 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -93,12 +93,16 @@ struct D3D12_HLSL_FUNCTION_DESC { }; enum D3D12_HLSL_ENUM_TYPE { + D3D12_HLSL_ENUM_TYPE_UINT, D3D12_HLSL_ENUM_TYPE_INT, D3D12_HLSL_ENUM_TYPE_UINT64_T, D3D12_HLSL_ENUM_TYPE_INT64_T, D3D12_HLSL_ENUM_TYPE_UINT16_T, - D3D12_HLSL_ENUM_TYPE_INT16_T + D3D12_HLSL_ENUM_TYPE_INT16_T, + + D3D12_HLSL_ENUM_TYPE_START = D3D12_HLSL_ENUM_TYPE_UINT, + D3D12_HLSL_ENUM_TYPE_END = D3D12_HLSL_ENUM_TYPE_INT16_T }; struct D3D12_HLSL_ENUM_DESC { diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 5f712c1c98..ea96ae0575 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1523,10 +1523,10 @@ struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus union { struct { - uint32_t NumSamplesOrStride; + uint32_t NumSamples; uint32_t NodeId; }; - uint64_t NumSamplesOrStrideNodeId; + uint64_t NumSamplesNodeId; }; union { @@ -1546,7 +1546,7 @@ struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus uint32_t BufferId) : Type(Type), BindPoint(BindPoint), BindCount(BindCount), uFlags(uFlags), ReturnType(ReturnType), Dimension(Dimension), - NumSamplesOrStride(NumSamples), Space(Space), NodeId(NodeId), + NumSamples(NumSamples), Space(Space), NodeId(NodeId), ArrayId(ArrayId), BufferId(BufferId) { assert(Type >= D3D_SIT_CBUFFER && Type <= D3D_SIT_UAV_FEEDBACKTEXTURE && @@ -1565,7 +1565,7 @@ struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus return TypeDimensionReturnTypeFlagsBindPoint == other.TypeDimensionReturnTypeFlagsBindPoint && SpaceBindCount == other.SpaceBindCount && - NumSamplesOrStrideNodeId == other.NumSamplesOrStrideNodeId && + NumSamplesNodeId == other.NumSamplesNodeId && ArrayIdBufferId == other.ArrayIdBufferId; } }; @@ -2404,6 +2404,30 @@ static void FillReflectionRegisterAt( uint32_t arrayId = PushArray(Refl, ArraySizeFlat, ArraySize); + uint32_t bufferId = 0; + D3D_CBUFFER_TYPE bufferType = D3D_CT_INTERFACE_POINTERS; //Invalid + + switch(inputType.registerType) { + + case D3D_SIT_CBUFFER: + case D3D_SIT_TBUFFER: + bufferType = D3D_CT_CBUFFER; + break; + + case D3D_SIT_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: + bufferType = D3D_CT_RESOURCE_BIND_INFO; + break; + } + + if(bufferType != D3D_CT_INTERFACE_POINTERS) { + Refl.Buffers.push_back({bufferType, nodeId}); + bufferId = (uint32_t) Refl.Buffers.size(); + } + DxcHLSLRegister regD3D12 = { inputType.RegisterType, @@ -2417,7 +2441,7 @@ static void FillReflectionRegisterAt( : AutoBindingSpace, nodeId, arrayId, - 0 + bufferId }; Refl.Registers.push_back(regD3D12); @@ -3387,6 +3411,159 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { EnumValues, header.EnumValues, Annotations, header.Annotations, ArraySizes, header.ArraySizes, Members, header.Members, Types, header.Types, Buffers, header.Buffers); + //Validation errors are throws to prevent accessing invalid data + + for(uint32_t i = 0; i < header.Sources; ++i) + if(Sources[i] >= header.Strings) + throw std::invalid_argument("Source path out of bounds"); + + for(uint32_t i = 0; i < header.Nodes; ++i) { + + const DxcHLSLNode &node = Nodes[i]; + + if( + node.NameId >= header.Strings || + node.FileNameId >= header.Sources || + node.GetAnnotationStart() + node.GetAnnotationCount() > header.Annotations || + node.GetNodeType() > DxcHLSLNodeType::End || + (i && node.GetParentId() >= i) || + i + node.GetChildCount() > header.Nodes + ) + throw std::invalid_argument("Node " + std::to_string(i) + " is invalid"); + + uint32_t maxValue = 1; + + switch(node.GetNodeType()) { + case DxcHLSLNodeType::Register: + maxValue = header.Registers; + break; + case DxcHLSLNodeType::Function: + maxValue = header.Functions; + break; + case DxcHLSLNodeType::Enum: + maxValue = header.Enums; + break; + case DxcHLSLNodeType::EnumValue: + maxValue = header.EnumValues; + break; + case DxcHLSLNodeType::Typedef: + case DxcHLSLNodeType::Using: + case DxcHLSLNodeType::Type: + maxValue = header.Types; + break; + case DxcHLSLNodeType::Variable: + maxValue = header.Variables; + break; + case DxcHLSLNodeType::Parameter: + throw std::invalid_argument("Node " + std::to_string(i) + " has unsupported 'parameter' type"); + break; + } + + if(node.GetLocalId() >= maxValue) + throw std::invalid_argument("Node " + std::to_string(i) + " has invalid localId"); + } + + for(uint32_t i = 0; i < header.Registers; ++i) { + + const DxcHLSLRegister ® = Registers[i]; + + if( + reg.NodeId >= header.Nodes || + Nodes[reg.NodeId].GetNodeType() != DxcHLSLNodeType::Register || + Nodes[reg.NodeId].GetLocalId() != i + ) + throw std::invalid_argument("Register " + std::to_string(i) + " points to an invalid nodeId"); + + if( + reg.Type > D3D_SIT_UAV_FEEDBACKTEXTURE || + reg.ReturnType > D3D_RETURN_TYPE_CONTINUED || + reg.Dimension > D3D_SRV_DIMENSION_BUFFEREX || + !reg.BindCount || + (reg.BindCount > 1 && reg.ArrayId >= header.Arrays) + ) + throw std::invalid_argument("Register " + std::to_string(i) + " invalid type, returnType, bindCount or dimension"); + + D3D_CBUFFER_TYPE bufferType = D3D_CT_INTERFACE_POINTERS; //Invalid + + switch(reg.Type) { + + case D3D_SIT_CBUFFER: + case D3D_SIT_TBUFFER: + bufferType = D3D_CT_CBUFFER; + break; + + case D3D_SIT_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: + bufferType = D3D_CT_RESOURCE_BIND_INFO; + break; + } + + //Check buffer + + if(bufferType != D3D_CT_INTERFACE_POINTERS) { + + if( + reg.BufferId >= header.Buffers || + Buffers[reg.BufferId].NodeId != reg.NodeId || + Buffers[reg.BufferId].Type !+ bufferType + ) + throw std::invalid_argument("Register " + std::to_string(i) + " invalid buffer referenced by register"); + + } + } + + for(uint32_t i = 0; i < header.Functions; ++i) { + + const DxcHLSLFunction &func = Functions[i]; + + if( + func.NodeId >= header.Nodes || + Nodes[func.NodeId].GetNodeType() != DxcHLSLNodeType::Function || + Nodes[func.NodeId].GetLocalId() != i + ) + throw std::invalid_argument("Function " + std::to_string(i) + " points to an invalid nodeId"); + } + + for(uint32_t i = 0; i < header.Enums; ++i) { + + const DxcHLSLEnumDesc &enm = Enums[i]; + + if( + enm.NodeId >= header.Nodes || + Nodes[enm.NodeId].GetNodeType() != DxcHLSLNodeType::Enum || + Nodes[enm.NodeId].GetLocalId() != i + ) + throw std::invalid_argument("Function " + std::to_string(i) + " points to an invalid nodeId"); + + if(enm.Type < D3D12_HLSL_ENUM_TYPE_START || enm.Type > D3D12_HLSL_ENUM_TYPE_END) + throw std::invalid_argument("Enum " + std::to_string(i) + " has an invalid type"); + } + + EnumValues, Array, ArraySizes, Members, + Types + + for(uint32_t i = 0; i < header.Annotations; ++i) + if(Annotations[i] >= header.Strings) + throw std::invalid_argument("Annotation " + std::to_string(i) + " points to an invalid string"); + + for(uint32_t i = 0; i < header.Buffers; ++i) { + + const DxcHLSLBuffer &buf = Buffers[i]; + + if( + buf.NodeId >= header.Nodes || + Nodes[buf.NodeId].GetNodeType() != DxcHLSLNodeType::Buffer || + Nodes[buf.NodeId].GetLocalId() != i + ) + throw std::invalid_argument("Buffer " + std::to_string(i) + " points to an invalid nodeId"); + } + + //TODO: Ensure EnumValue is a child of Enum + // Ensure Variable is a child of Buffer? + //TODO: Run validation!!! }; From c590bd9cfa2c4e17d09a4ea84308067523366f5e Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 30 Aug 2025 17:50:04 +0200 Subject: [PATCH 020/126] Added full validation for the loaded reflection binary to ensure no invalid user data is passed that may crash the caller. Also fixed a few issues that were found by writing this validator --- .../clang/tools/libclang/dxcrewriteunused.cpp | 357 +++++++++++++----- 1 file changed, 268 insertions(+), 89 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index ea96ae0575..128e65968b 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1471,7 +1471,8 @@ struct DxcHLSLFunction { DxcHLSLFunction(uint32_t NodeId, uint32_t NumParameters, bool HasReturn, bool HasDefinition) - : NumParametersHasReturnAndDefinition(NumParameters | + : NodeId(NodeId), + NumParametersHasReturnAndDefinition(NumParameters | (HasReturn ? (1 << 30) : 0) | (HasDefinition ? (1 << 31) : 0)) { @@ -1531,7 +1532,7 @@ struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus union { struct { - uint32_t ArrayId; // Only if BindCount > 1 and the array is 2D+ + uint32_t ArrayId; // Only if BindCount > 1 and the array is 2D+ (else -1) uint32_t BufferId; // If cbuffer or structured buffer }; uint64_t ArrayIdBufferId; @@ -2374,6 +2375,28 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, return i; } +D3D_CBUFFER_TYPE GetBufferType(uint8_t Type) { + + switch (Type) { + + case D3D_SIT_CBUFFER: + return D3D_CT_CBUFFER; + + case D3D_SIT_TBUFFER: + return D3D_CT_TBUFFER; + + case D3D_SIT_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: + return D3D_CT_RESOURCE_BIND_INFO; + + default: + return D3D_CT_INTERFACE_POINTERS; + } +} + static void FillReflectionRegisterAt( const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, @@ -2405,27 +2428,11 @@ static void FillReflectionRegisterAt( uint32_t arrayId = PushArray(Refl, ArraySizeFlat, ArraySize); uint32_t bufferId = 0; - D3D_CBUFFER_TYPE bufferType = D3D_CT_INTERFACE_POINTERS; //Invalid - - switch(inputType.registerType) { - - case D3D_SIT_CBUFFER: - case D3D_SIT_TBUFFER: - bufferType = D3D_CT_CBUFFER; - break; - - case D3D_SIT_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED: - case D3D_SIT_UAV_APPEND_STRUCTURED: - case D3D_SIT_UAV_CONSUME_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: - bufferType = D3D_CT_RESOURCE_BIND_INFO; - break; - } + D3D_CBUFFER_TYPE bufferType = GetBufferType(inputType.RegisterType); if(bufferType != D3D_CT_INTERFACE_POINTERS) { - Refl.Buffers.push_back({bufferType, nodeId}); bufferId = (uint32_t) Refl.Buffers.size(); + Refl.Buffers.push_back({bufferType, nodeId}); } DxcHLSLRegister regD3D12 = { @@ -2979,7 +2986,7 @@ std::string GetBuiltinTypeName(const DxcReflectionData &Refl, "Texture2D", "Texture3D", "TextureCube", - NULL, + "SamplerState", NULL, NULL, NULL, @@ -3449,14 +3456,11 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { case DxcHLSLNodeType::Typedef: case DxcHLSLNodeType::Using: case DxcHLSLNodeType::Type: - maxValue = header.Types; - break; case DxcHLSLNodeType::Variable: - maxValue = header.Variables; + maxValue = header.Types; break; case DxcHLSLNodeType::Parameter: throw std::invalid_argument("Node " + std::to_string(i) + " has unsupported 'parameter' type"); - break; } if(node.GetLocalId() >= maxValue) @@ -3474,44 +3478,24 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { ) throw std::invalid_argument("Register " + std::to_string(i) + " points to an invalid nodeId"); - if( - reg.Type > D3D_SIT_UAV_FEEDBACKTEXTURE || - reg.ReturnType > D3D_RETURN_TYPE_CONTINUED || - reg.Dimension > D3D_SRV_DIMENSION_BUFFEREX || - !reg.BindCount || - (reg.BindCount > 1 && reg.ArrayId >= header.Arrays) - ) - throw std::invalid_argument("Register " + std::to_string(i) + " invalid type, returnType, bindCount or dimension"); + if (reg.Type > D3D_SIT_UAV_FEEDBACKTEXTURE || + reg.ReturnType > D3D_RETURN_TYPE_CONTINUED || + reg.Dimension > D3D_SRV_DIMENSION_BUFFEREX || !reg.BindCount || + (reg.ArrayId != uint32_t(-1) && reg.ArrayId >= header.Arrays) || + (reg.ArrayId != uint32_t(-1) && reg.BindCount <= 1)) + throw std::invalid_argument( + "Register " + std::to_string(i) + + " invalid type, returnType, bindCount, array or dimension"); - D3D_CBUFFER_TYPE bufferType = D3D_CT_INTERFACE_POINTERS; //Invalid - - switch(reg.Type) { - - case D3D_SIT_CBUFFER: - case D3D_SIT_TBUFFER: - bufferType = D3D_CT_CBUFFER; - break; - - case D3D_SIT_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED: - case D3D_SIT_UAV_APPEND_STRUCTURED: - case D3D_SIT_UAV_CONSUME_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: - bufferType = D3D_CT_RESOURCE_BIND_INFO; - break; - } - - //Check buffer + D3D_CBUFFER_TYPE bufferType = GetBufferType(reg.Type); if(bufferType != D3D_CT_INTERFACE_POINTERS) { - if( - reg.BufferId >= header.Buffers || - Buffers[reg.BufferId].NodeId != reg.NodeId || - Buffers[reg.BufferId].Type !+ bufferType - ) - throw std::invalid_argument("Register " + std::to_string(i) + " invalid buffer referenced by register"); - + if (reg.BufferId >= header.Buffers || + Buffers[reg.BufferId].NodeId != reg.NodeId || + Buffers[reg.BufferId].Type != bufferType) + throw std::invalid_argument("Register " + std::to_string(i) + + " invalid buffer referenced by register"); } } @@ -3519,53 +3503,248 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { const DxcHLSLFunction &func = Functions[i]; - if( - func.NodeId >= header.Nodes || - Nodes[func.NodeId].GetNodeType() != DxcHLSLNodeType::Function || - Nodes[func.NodeId].GetLocalId() != i - ) - throw std::invalid_argument("Function " + std::to_string(i) + " points to an invalid nodeId"); + if (func.NodeId >= header.Nodes || + Nodes[func.NodeId].GetNodeType() != DxcHLSLNodeType::Function || + Nodes[func.NodeId].GetLocalId() != i) + throw std::invalid_argument("Function " + std::to_string(i) + + " points to an invalid nodeId"); } for(uint32_t i = 0; i < header.Enums; ++i) { const DxcHLSLEnumDesc &enm = Enums[i]; - if( - enm.NodeId >= header.Nodes || - Nodes[enm.NodeId].GetNodeType() != DxcHLSLNodeType::Enum || - Nodes[enm.NodeId].GetLocalId() != i - ) - throw std::invalid_argument("Function " + std::to_string(i) + " points to an invalid nodeId"); + if (enm.NodeId >= header.Nodes || + Nodes[enm.NodeId].GetNodeType() != DxcHLSLNodeType::Enum || + Nodes[enm.NodeId].GetLocalId() != i) + throw std::invalid_argument("Function " + std::to_string(i) + + " points to an invalid nodeId"); - if(enm.Type < D3D12_HLSL_ENUM_TYPE_START || enm.Type > D3D12_HLSL_ENUM_TYPE_END) - throw std::invalid_argument("Enum " + std::to_string(i) + " has an invalid type"); - } + if (enm.Type < D3D12_HLSL_ENUM_TYPE_START || + enm.Type > D3D12_HLSL_ENUM_TYPE_END) + throw std::invalid_argument("Enum " + std::to_string(i) + + " has an invalid type"); - EnumValues, Array, ArraySizes, Members, - Types + const DxcHLSLNode &node = Nodes[enm.NodeId]; - for(uint32_t i = 0; i < header.Annotations; ++i) - if(Annotations[i] >= header.Strings) - throw std::invalid_argument("Annotation " + std::to_string(i) + " points to an invalid string"); + for (uint32_t j = 0; j < node.GetChildCount(); ++j) { + + const DxcHLSLNode &child = Nodes[enm.NodeId + 1 + j]; - for(uint32_t i = 0; i < header.Buffers; ++i) { + if (child.GetChildCount() != 0 || + child.GetNodeType() != DxcHLSLNodeType::EnumValue) + throw std::invalid_argument("Enum " + std::to_string(i) + + " has an invalid enum value"); + } + } + + for(uint32_t i = 0; i < header.EnumValues; ++i) { + const DxcHLSLEnumValue &enumVal = EnumValues[i]; + + if (enumVal.NodeId >= header.Nodes || + Nodes[enumVal.NodeId].GetNodeType() != DxcHLSLNodeType::EnumValue || + Nodes[enumVal.NodeId].GetLocalId() != i || + Nodes[Nodes[enumVal.NodeId].GetParentId()].GetNodeType() != + DxcHLSLNodeType::Enum) + throw std::invalid_argument("Enum " + std::to_string(i) + + " points to an invalid nodeId"); + } + + for (uint32_t i = 0; i < header.Arrays; ++i) { + + const DxcHLSLArray &arr = Arrays[i]; + + if (arr.ArrayElem() <= 1 || arr.ArrayElem() > 8 || + arr.ArrayStart() + arr.ArrayElem() > header.ArraySizes) + throw std::invalid_argument("Array " + std::to_string(i) + + " points to an invalid array element"); + } + + for (uint32_t i = 0; i < header.Members; ++i) { + + const DxcHLSLMember &mem = Members[i]; + + if (mem.NameId >= header.Strings || mem.TypeId >= header.Types) + throw std::invalid_argument("Member " + std::to_string(i) + + " points to an invalid string or type"); + } + + for (uint32_t i = 0; i < header.Annotations; ++i) + if (Annotations[i] >= header.Strings) + throw std::invalid_argument("Annotation " + std::to_string(i) + + " points to an invalid string"); + + for (uint32_t i = 0; i < header.Buffers; ++i) { + const DxcHLSLBuffer &buf = Buffers[i]; - if( - buf.NodeId >= header.Nodes || - Nodes[buf.NodeId].GetNodeType() != DxcHLSLNodeType::Buffer || - Nodes[buf.NodeId].GetLocalId() != i - ) - throw std::invalid_argument("Buffer " + std::to_string(i) + " points to an invalid nodeId"); + if (buf.NodeId >= header.Nodes || + Nodes[buf.NodeId].GetNodeType() != DxcHLSLNodeType::Register || + Nodes[buf.NodeId].GetLocalId() >= header.Registers || + Registers[Nodes[buf.NodeId].GetLocalId()].BufferId != i) + throw std::invalid_argument("Buffer " + std::to_string(i) + + " points to an invalid nodeId"); + + const DxcHLSLNode &node = Nodes[buf.NodeId]; + + if (!node.GetChildCount()) + throw std::invalid_argument("Buffer " + std::to_string(i) + + " requires at least one Variable child"); + + for (uint32_t j = 0; j < node.GetChildCount(); ++j) { + + const DxcHLSLNode &child = Nodes[buf.NodeId + 1 + j]; + + if (child.GetChildCount() != 0 || + child.GetNodeType() != DxcHLSLNodeType::Variable) + throw std::invalid_argument("Buffer " + std::to_string(i) + + " has to have only Variable child nodes"); + } + } + + for (uint32_t i = 0; i < header.Members; ++i) { + + const DxcHLSLMember &mem = Members[i]; + + if (mem.NameId >= header.Strings || mem.TypeId >= header.Types) + throw std::invalid_argument("Member " + std::to_string(i) + + " points to an invalid string or type"); } + + for (uint32_t i = 0; i < header.Types; ++i) { + + const DxcHLSLType &type = Types[i]; + + if (type.NameId >= header.Strings || + (type.BaseClass != uint32_t(-1) && type.BaseClass >= header.Types) || + (uint64_t)type.MembersStart + type.MembersCount > header.Members || + (type.ElementsOrArrayId >> 31 && + (type.ElementsOrArrayId << 1 >> 1) >= header.Arrays)) + throw std::invalid_argument( + "Type " + std::to_string(i) + + " points to an invalid string, base class or member"); + + switch (type.Class) { + + case D3D_SVC_SCALAR: - //TODO: Ensure EnumValue is a child of Enum - // Ensure Variable is a child of Buffer? + if (type.Columns != 1) + throw std::invalid_argument("Type (scalar) " + std::to_string(i) + + " should have columns == 1"); - //TODO: Run validation!!! + [[fallthrough]]; + case D3D_SVC_VECTOR: + + if (type.Rows != 1) + throw std::invalid_argument("Type (scalar/vector) " + + std::to_string(i) + + " should have rows == 1"); + + [[fallthrough]]; + + case D3D_SVC_MATRIX_ROWS: + case D3D_SVC_MATRIX_COLUMNS: + + if (!type.Rows || !type.Columns || type.Rows > 128 || type.Columns > 128) + throw std::invalid_argument("Type (scalar/vector/matrix) " + + std::to_string(i) + + " has invalid rows or columns"); + + switch (type.Type) { + case D3D_SVT_BOOL: + case D3D_SVT_INT: + case D3D_SVT_FLOAT: + case D3D_SVT_MIN8FLOAT: + case D3D_SVT_MIN10FLOAT: + case D3D_SVT_MIN16FLOAT: + case D3D_SVT_MIN12INT: + case D3D_SVT_MIN16INT: + case D3D_SVT_MIN16UINT: + case D3D_SVT_INT16: + case D3D_SVT_UINT16: + case D3D_SVT_FLOAT16: + case D3D_SVT_INT64: + case D3D_SVT_UINT64: + case D3D_SVT_UINT: + case D3D_SVT_DOUBLE: + break; + + default: + throw std::invalid_argument("Type (scalar/matrix/vector) " + + std::to_string(i) + + " is of invalid type"); + } + + break; + + case D3D_SVC_STRUCT: + + if (!type.MembersCount) + throw std::invalid_argument("Type (struct) " + std::to_string(i) + + " is missing children"); + if (type.Type) + throw std::invalid_argument("Type (struct) " + + std::to_string(i) + + " shouldn't have rows or columns"); + + if (type.Rows || type.Columns) + throw std::invalid_argument("Type (struct) " + + std::to_string(i) + + " shouldn't have rows or columns"); + + break; + + case D3D_SVC_OBJECT: + + switch (type.Type) { + + case D3D_SVT_STRING: + case D3D_SVT_TEXTURE1D: + case D3D_SVT_TEXTURE2D: + case D3D_SVT_TEXTURE3D: + case D3D_SVT_TEXTURECUBE: + case D3D_SVT_SAMPLER: + case D3D_SVT_BUFFER: + case D3D_SVT_CBUFFER: + case D3D_SVT_TBUFFER: + case D3D_SVT_TEXTURE1DARRAY: + case D3D_SVT_TEXTURE2DARRAY: + case D3D_SVT_TEXTURE2DMS: + case D3D_SVT_TEXTURE2DMSARRAY: + case D3D_SVT_TEXTURECUBEARRAY: + case D3D_SVT_RWTEXTURE1D: + case D3D_SVT_RWTEXTURE1DARRAY: + case D3D_SVT_RWTEXTURE2D: + case D3D_SVT_RWTEXTURE2DARRAY: + case D3D_SVT_RWTEXTURE3D: + case D3D_SVT_RWBUFFER: + case D3D_SVT_BYTEADDRESS_BUFFER: + case D3D_SVT_RWBYTEADDRESS_BUFFER: + case D3D_SVT_STRUCTURED_BUFFER: + case D3D_SVT_RWSTRUCTURED_BUFFER: + case D3D_SVT_APPEND_STRUCTURED_BUFFER: + case D3D_SVT_CONSUME_STRUCTURED_BUFFER: + break; + + default: + throw std::invalid_argument("Type (object) " + std::to_string(i) + + " is of invalid type"); + } + + if (type.Rows || type.Columns) + throw std::invalid_argument("Type (object) " + + std::to_string(i) + + " shouldn't have rows or columns"); + + break; + + default: + throw std::invalid_argument("Type " + std::to_string(i) + + " has an invalid class"); + } + } }; static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, From 94b18be7b842d75989fbe2db203653f73db3d50a Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 30 Aug 2025 18:15:39 +0200 Subject: [PATCH 021/126] Renamed hlsl function internals feature to scopes to better reflect what it does. Exposed the feature flags of reflection to the internal and external struct to allow tools to know what features were used when exporting. --- include/dxc/Support/HLSLOptions.h | 2 +- include/dxc/Support/HLSLOptions.td | 4 +- include/dxc/dxctools.h | 21 +++++ lib/DxcSupport/HLSLOptions.cpp | 4 +- .../clang/tools/libclang/dxcrewriteunused.cpp | 78 +++++++++---------- 5 files changed, 65 insertions(+), 44 deletions(-) diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index ca5740caa6..1c4140c4a8 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -108,7 +108,7 @@ struct RewriterOpts { bool ReflectHLSLFunctions = false; // OPT_rw_reflect_hlsl_functions bool ReflectHLSLNamespaces = false; // OPT_rw_reflect_hlsl_namespaces bool ReflectHLSLUserTypes = false; // OPT_rw_reflect_hlsl_user_types - bool ReflectHLSLFunctionInternals = false; // OPT_rw_reflect_hlsl_function_internals + bool ReflectHLSLScopes = false; // OPT_rw_reflect_hlsl_scopes bool ReflectHLSLVariables = false; // OPT_rw_reflect_hlsl_variables bool SkipFunctionBody = false; // OPT_rw_skip_function_body bool SkipStatic = false; // OPT_rw_skip_static diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index e7b36580eb..2d017488ca 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -573,8 +573,8 @@ def rw_reflect_hlsl_namespaces : Flag<["-", "/"], "reflect-hlsl-namespaces">, Gr HelpText<"Reflect HLSL nodes in namespaces rather than only the root namespace.">; def rw_reflect_hlsl_user_types : Flag<["-", "/"], "reflect-hlsl-user-types">, Group, Flags<[RewriteOption]>, HelpText<"Reflect HLSL user types (typedef, using, struct, enum).">; -def rw_reflect_hlsl_function_internals : Flag<["-", "/"], "reflect-hlsl-function-internals">, Group, Flags<[RewriteOption]>, - HelpText<"Reflect HLSL function internals (variables and structs defined in functions).">; +def rw_reflect_hlsl_scopes : Flag<["-", "/"], "reflect-hlsl-scopes">, Group, Flags<[RewriteOption]>, + HelpText<"Reflect HLSL scopes (variables and structs defined in functions, structs and scopes).">; def rw_reflect_hlsl_variables : Flag<["-", "/"], "reflect-hlsl-variables">, Group, Flags<[RewriteOption]>, HelpText<"Reflect HLSL static variables.">; def rw_skip_function_body : Flag<["-", "/"], "skip-fn-body">, Group, Flags<[RewriteOption]>, diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index af2f746256..acca85f6bd 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -76,7 +76,28 @@ struct IDxcRewriter2 : public IDxcRewriter { //You could use it to find all entrypoints even if [shader("")] isn't used, //Find struct/enum information, find out about optimized out registers, etc. +enum D3D12_HLSL_REFLECTION_FEATURE { + + D3D12_HLSL_REFLECTION_FEATURE_NONE = 0, + + // Includes cbuffer and registers only + D3D12_HLSL_REFLECTION_FEATURE_BASICS = 1 << 0, + + D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS = 1 << 1, + D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES = 1 << 2, + + // Include user types (struct, enum, typedef, etc.) + D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES = 1 << 3, + + // Variables, structs, functions defined in functions, scopes & structs + D3D12_HLSL_REFLECTION_FEATURE_SCOPES = 1 << 4, + + // Variables not included in $Global or cbuffers + D3D12_HLSL_REFLECTION_FEATURE_VARIABLES = 1 << 5 +}; + struct D3D12_HLSL_REFLECTION_DESC { + D3D12_HLSL_REFLECTION_FEATURE Features; UINT ConstantBufferCount; UINT ResourceCount; UINT FunctionCount; diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index 96a06d54e3..e69df1df1c 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -1359,8 +1359,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, Args.hasFlag(OPT_rw_reflect_hlsl_namespaces, OPT_INVALID, false); opts.RWOpt.ReflectHLSLUserTypes = Args.hasFlag(OPT_rw_reflect_hlsl_user_types, OPT_INVALID, false); - opts.RWOpt.ReflectHLSLFunctionInternals = - Args.hasFlag(OPT_rw_reflect_hlsl_function_internals, OPT_INVALID, false); + opts.RWOpt.ReflectHLSLScopes = + Args.hasFlag(OPT_rw_reflect_hlsl_scopes, OPT_INVALID, false); opts.RWOpt.ReflectHLSLVariables = Args.hasFlag(OPT_rw_reflect_hlsl_variables, OPT_INVALID, false); opts.RWOpt.SkipFunctionBody = diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 128e65968b..c17378f4b2 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1079,8 +1079,6 @@ using UnresolvedRegisters = llvm::SmallVector; // Find gap in register list and fill it -//TODO: Niels, check multi dim arrays - uint32_t FillNextRegister(llvm::SmallVector &ranges, uint32_t arraySize) { @@ -1686,6 +1684,8 @@ struct DxcHLSLBuffer { // Almost maps to CShaderReflectionConstantBuffer and struct DxcReflectionData { + D3D12_HLSL_REFLECTION_FEATURE Features; + std::vector Strings; std::unordered_map StringsToId; @@ -2607,18 +2607,9 @@ static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, //It's a struct, add parameters recursively }*/ -enum ReflectionMask : uint32_t { - ReflectionMask_None = 0, - ReflectionMask_Basics = 1 << 0, //Includes cbuffer and registers - ReflectionMask_Functions = 1 << 1, - ReflectionMask_Namespaces = 1 << 2, - ReflectionMask_UserTypes = 1 << 3, //Include user types (struct, enum, typedef, etc.) - ReflectionMask_FunctionInternals = 1 << 4, //Variables, structs, functions defined in functions - ReflectionMask_Variables = 1 << 5 //Variables not included in $Global or cbuffers -}; - -ReflectionMask& operator|=(ReflectionMask &a, ReflectionMask b) { - return a = (ReflectionMask)((uint32_t)a | (uint32_t)b); +D3D12_HLSL_REFLECTION_FEATURE &operator|=(D3D12_HLSL_REFLECTION_FEATURE &a, + D3D12_HLSL_REFLECTION_FEATURE b) { + return a = (D3D12_HLSL_REFLECTION_FEATURE)((uint32_t)a | (uint32_t)b); } static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, @@ -2627,7 +2618,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DxcReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, - ReflectionMask InclusionFlags, + D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj) { PrintfStream pfStream; @@ -2654,7 +2645,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (HLSLBufferDecl *CBuffer = dyn_cast(it)) { - if(!(InclusionFlags & ReflectionMask_Basics)) + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) continue; // TODO: Add for reflection even though it might not be important @@ -2706,7 +2697,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (FunctionDecl *Func = dyn_cast(it)) { - if (!(InclusionFlags & ReflectionMask_Functions)) + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS)) continue; const FunctionDecl *Definition = nullptr; @@ -2732,16 +2723,16 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, Refl.Functions.push_back(std::move(func)); - if (hasDefinition && (InclusionFlags & ReflectionMask_FunctionInternals)) { + if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, InclusionFlags, + AutoBindingSpace, Depth + 1, Features, nodeId, DefaultRowMaj); } } else if (FieldDecl *Field = dyn_cast(it)) { - if (!(InclusionFlags & ReflectionMask_UserTypes)) + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) continue; //Field->print(pfStream, printingPolicy); @@ -2749,7 +2740,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (TypedefDecl *Typedef = dyn_cast(it)) { - if (!(InclusionFlags & ReflectionMask_UserTypes)) + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) continue; // Typedef->print(pfStream, printingPolicy); @@ -2757,7 +2748,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (TypeAliasDecl *TypeAlias = dyn_cast(it)) { - if (!(InclusionFlags & ReflectionMask_UserTypes)) + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) continue; // TypeAlias->print(pfStream, printingPolicy); @@ -2765,7 +2756,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (EnumDecl *Enum = dyn_cast(it)) { - if (!(InclusionFlags & ReflectionMask_UserTypes)) + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) continue; uint32_t nodeId = PushNextNodeId( @@ -2818,7 +2809,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (ValueDecl *ValDecl = dyn_cast(it)) { - if(!(InclusionFlags & ReflectionMask_Basics)) + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) continue; //TODO: Handle values @@ -2852,7 +2843,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (RecordDecl *RecDecl = dyn_cast(it)) { - if (!(InclusionFlags & ReflectionMask_UserTypes)) + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) continue; //RecDecl->print(pfStream, printingPolicy); @@ -2862,7 +2853,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, else if (NamespaceDecl *Namespace = dyn_cast(it)) { - if (!(InclusionFlags & ReflectionMask_Namespaces)) + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES)) continue; uint32_t nodeId = PushNextNodeId( @@ -2870,20 +2861,23 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DxcHLSLNodeType::Namespace, ParentNodeId, 0); RecursiveReflectHLSL(*Namespace, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, InclusionFlags, nodeId, + AutoBindingSpace, Depth + 1, Features, nodeId, DefaultRowMaj); } } } static void ReflectHLSL(ASTHelper &astHelper, DxcReflectionData& Refl, - uint32_t AutoBindingSpace, ReflectionMask ReflectMask, + uint32_t AutoBindingSpace, + D3D12_HLSL_REFLECTION_FEATURE Features, bool DefaultRowMaj) { TranslationUnitDecl &Ctx = *astHelper.tu; DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); const SourceManager &SM = astHelper.compiler.getSourceManager(); + Refl = {}; + Refl.Features = Features; Refl.Strings.push_back(""); Refl.StringsToId[""] = 0; @@ -2891,7 +2885,7 @@ static void ReflectHLSL(ASTHelper &astHelper, DxcReflectionData& Refl, 0xFFFF, 0, 0, 0, 0, 0}); RecursiveReflectHLSL(Ctx, astHelper.compiler.getASTContext(), Diags, SM, Refl, - AutoBindingSpace, 0, ReflectMask, 0, DefaultRowMaj); + AutoBindingSpace, 0, Features, 0, DefaultRowMaj); } static void GlobalVariableAsExternByDefault(DeclContext &Ctx) { @@ -3199,6 +3193,8 @@ struct DxcHLSLHeader { uint16_t Version; uint16_t Sources; + D3D12_HLSL_REFLECTION_FEATURE Features; + uint32_t Strings; uint32_t Nodes; @@ -3387,7 +3383,7 @@ void DxcReflectionData::Dump(std::vector &Bytes) const { UnsafeCast(Bytes, toReserve) = { DxcReflectionDataMagic, DxcReflectionDataVersion, - uint16_t(Sources.size()), uint32_t(Strings.size()), + uint16_t(Sources.size()), Features, uint32_t(Strings.size()), uint32_t(Nodes.size()), uint32_t(Registers.size()), uint32_t(Functions.size()), uint32_t(Enums.size()), uint32_t(EnumValues.size()), uint32_t(Annotations.size()), @@ -3413,6 +3409,8 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { if (header.Version != DxcReflectionDataVersion) throw std::invalid_argument("Unrecognized version number"); + Features = header.Features; + Consume(Bytes, off, Strings, header.Strings, Sources, header.Sources, Nodes, header.Nodes, Registers, header.Registers, Functions, header.Functions, Enums, header.Enums, EnumValues, header.EnumValues, Annotations, header.Annotations, ArraySizes, header.ArraySizes, Members, @@ -3767,25 +3765,26 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, GenerateConsistentBindings(*tu, opts.AutoBindingSpace); } - ReflectionMask reflectMask = ReflectionMask_None; + D3D12_HLSL_REFLECTION_FEATURE reflectMask = + D3D12_HLSL_REFLECTION_FEATURE_NONE; if(opts.RWOpt.ReflectHLSLBasics) - reflectMask |= ReflectionMask_Basics; + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_BASICS; if(opts.RWOpt.ReflectHLSLFunctions) - reflectMask |= ReflectionMask_Functions; + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS; if(opts.RWOpt.ReflectHLSLNamespaces) - reflectMask |= ReflectionMask_Namespaces; + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES; if(opts.RWOpt.ReflectHLSLUserTypes) - reflectMask |= ReflectionMask_UserTypes; + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES; - if(opts.RWOpt.ReflectHLSLFunctionInternals) - reflectMask |= ReflectionMask_FunctionInternals; + if(opts.RWOpt.ReflectHLSLScopes) + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SCOPES; if(opts.RWOpt.ReflectHLSLVariables) - reflectMask |= ReflectionMask_Variables; + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_VARIABLES; if (reflectMask) { @@ -3823,7 +3822,8 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, opts.RWOpt.RemoveUnusedFunctions, w); if (FAILED(hr)) return hr; - } else if (!opts.RWOpt.ConsistentBindings && (reflectMask & ReflectionMask_Basics)) { + } else if (!opts.RWOpt.ConsistentBindings && + (reflectMask & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) { o << "// Rewrite unchanged result:\n"; } From ece3cb1785a05c97fc58a3093426a8420f85d06c Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 31 Aug 2025 00:08:55 +0200 Subject: [PATCH 022/126] Added option to disable debug info, which is useful if you want the AST but you already have the nodeId -> names somewhere or you have no use for it (e.g. you only want to know what data is in 't0, space5', but no need for other type info). Split node and node symbol data as well as type name and member name which allows an AST without any names. Node and symbol are now (somewhat) tightly packed relative to cache size. Annotations are now stored in a StringsNonDebug list that gets preserved even when stripping debug data. --- include/dxc/Support/HLSLOptions.h | 1 + include/dxc/Support/HLSLOptions.td | 2 + include/dxc/dxctools.h | 5 +- lib/DxcSupport/HLSLOptions.cpp | 2 + .../clang/tools/libclang/dxcrewriteunused.cpp | 538 +++++++++++------- 5 files changed, 337 insertions(+), 211 deletions(-) diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index 1c4140c4a8..362482a981 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -110,6 +110,7 @@ struct RewriterOpts { bool ReflectHLSLUserTypes = false; // OPT_rw_reflect_hlsl_user_types bool ReflectHLSLScopes = false; // OPT_rw_reflect_hlsl_scopes bool ReflectHLSLVariables = false; // OPT_rw_reflect_hlsl_variables + bool ReflectHLSLDisableSymbols = false; // OPT_rw_reflect_hlsl_disable_symbols bool SkipFunctionBody = false; // OPT_rw_skip_function_body bool SkipStatic = false; // OPT_rw_skip_static bool GlobalExternByDefault = false; // OPT_rw_global_extern_by_default diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index 2d017488ca..3bc9bafc78 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -577,6 +577,8 @@ def rw_reflect_hlsl_scopes : Flag<["-", "/"], "reflect-hlsl-scopes">, Group; def rw_reflect_hlsl_variables : Flag<["-", "/"], "reflect-hlsl-variables">, Group, Flags<[RewriteOption]>, HelpText<"Reflect HLSL static variables.">; +def rw_reflect_hlsl_disable_symbols : Flag<["-", "/"], "reflect-hlsl-disable-symbols">, Group, Flags<[RewriteOption]>, + HelpText<"Reflect HLSL disable symbols.">; def rw_skip_function_body : Flag<["-", "/"], "skip-fn-body">, Group, Flags<[RewriteOption]>, HelpText<"Translate function definitions to declarations">; def rw_skip_static : Flag<["-", "/"], "skip-static">, Group, Flags<[RewriteOption]>, diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index acca85f6bd..5c2cdf7dfa 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -93,7 +93,10 @@ enum D3D12_HLSL_REFLECTION_FEATURE { D3D12_HLSL_REFLECTION_FEATURE_SCOPES = 1 << 4, // Variables not included in $Global or cbuffers - D3D12_HLSL_REFLECTION_FEATURE_VARIABLES = 1 << 5 + D3D12_HLSL_REFLECTION_FEATURE_VARIABLES = 1 << 5, + + // Symbol info (stripping this will remove names and file location info) + D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO = 1 << 6 }; struct D3D12_HLSL_REFLECTION_DESC { diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index e69df1df1c..a28c999d5b 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -1363,6 +1363,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, Args.hasFlag(OPT_rw_reflect_hlsl_scopes, OPT_INVALID, false); opts.RWOpt.ReflectHLSLVariables = Args.hasFlag(OPT_rw_reflect_hlsl_variables, OPT_INVALID, false); + opts.RWOpt.ReflectHLSLDisableSymbols = + Args.hasFlag(OPT_rw_reflect_hlsl_disable_symbols, OPT_INVALID, false); opts.RWOpt.SkipFunctionBody = Args.hasFlag(OPT_rw_skip_function_body, OPT_INVALID, false); opts.RWOpt.SkipStatic = diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index c17378f4b2..e440c4f134 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1294,55 +1294,85 @@ enum class DxcHLSLNodeType : uint64_t { End = Type }; -struct DxcHLSLNode { +struct DxcHLSLNodeSymbol { union { struct { uint32_t NameId; // Local name (not including parent's name) - uint16_t FileNameId; + uint16_t FileNameId; //-1 == no file info uint16_t SourceLineCount; }; uint64_t NameIdFileNameIdSourceLineCount; }; - uint64_t LocalIdAnnotationSourceLineStart; - - uint64_t TypeChildsParentAnnotationsSourceColumnHi; - union { struct { uint16_t SourceColumnStartLo; uint16_t SourceColumnEndLo; - uint32_t Padding; + uint32_t ColumnHiSourceLinePad; // 2 : 20 : 10 }; uint64_t SourceColumnStartEndLo; }; - DxcHLSLNode() = default; - - DxcHLSLNode(uint32_t NameId, + DxcHLSLNodeSymbol() = default; - DxcHLSLNodeType NodeType, uint32_t LocalId, - uint32_t AnnotationStart, uint16_t FileNameId, - - uint32_t ChildCount, uint32_t ParentId, uint16_t SourceLineCount, - - uint32_t SourceLineStart, uint32_t SourceColumnStart, - uint32_t SourceColumnEnd, uint16_t AnnotationCount) + DxcHLSLNodeSymbol(uint32_t NameId, uint16_t FileNameId, + uint16_t SourceLineCount, uint32_t SourceLineStart, + uint32_t SourceColumnStart, uint32_t SourceColumnEnd) : NameId(NameId), FileNameId(FileNameId), SourceLineCount(SourceLineCount), SourceColumnStartLo(uint16_t(SourceColumnStart)), SourceColumnEndLo(uint16_t(SourceColumnEnd)), - LocalIdAnnotationSourceLineStart((uint64_t(LocalId) << (64 - 24)) | - (uint64_t(AnnotationStart) << 20) | - SourceLineStart), - TypeChildsParentAnnotationsSourceColumnHi((uint64_t(NodeType) << 60) | - (uint64_t(ChildCount) << (10 + 2 + 24)) | - (uint64_t(AnnotationCount) << (2 + 24)) | - (SourceColumnStart >> 16 << 24) | - (SourceColumnEnd >> 16 << 25) | - (ParentId)) { + ColumnHiSourceLinePad((SourceColumnStart >> 16) | + (SourceColumnEnd >> 16 << 1) | + (SourceLineStart << 2)) { + + assert(SourceColumnStart < (1 << 17) && "SourceColumnStart out of bounds"); + assert(SourceColumnEnd < (1 << 17) && "SourceColumnEnd out of bounds"); + + assert(SourceLineStart < ((1 << 20) - 1) && + "SourceLineStart out of bounds"); + } + + uint32_t GetSourceLineStart() const { + return uint32_t(ColumnHiSourceLinePad >> 2); + } + + uint32_t GetSourceColumnStart() const { + return SourceColumnStartLo | ((ColumnHiSourceLinePad & 1) << 16); + } + + uint32_t GetSourceColumnEnd() const { + return SourceColumnEndLo | ((ColumnHiSourceLinePad & 2) << 15); + } + + bool operator==(const DxcHLSLNodeSymbol &other) const { + return NameIdFileNameIdSourceLineCount == + other.NameIdFileNameIdSourceLineCount && + SourceColumnStartEndLo == other.SourceColumnStartEndLo; + } +}; + +struct DxcHLSLNode { + + uint32_t LocalIdParentLo; //24 : 8 + uint32_t ParentHiAnnotationsType; //16 : 10 : 6 + uint32_t ChildCountPad; //24 : 8 + uint32_t AnnotationStartPad; //20 : 12 + + DxcHLSLNode() = default; + + DxcHLSLNode(DxcHLSLNodeType NodeType, uint32_t LocalId, + uint32_t AnnotationStart, uint32_t ChildCount, uint32_t ParentId, + uint16_t AnnotationCount) + : LocalIdParentLo(LocalId | (ParentId << 24)), + ChildCountPad(ChildCount), + AnnotationStartPad(AnnotationStart), + ParentHiAnnotationsType( + (uint32_t(NodeType) << 26) | + (uint32_t(AnnotationCount) << 16) | + (ParentId >> 8)) { assert(NodeType >= DxcHLSLNodeType::Start && NodeType <= DxcHLSLNodeType::End && "Invalid enum value"); @@ -1350,76 +1380,40 @@ struct DxcHLSLNode { assert(LocalId < ((1 << 24) - 1) && "LocalId out of bounds"); assert(ParentId < ((1 << 24) - 1) && "ParentId out of bounds"); assert(ChildCount < ((1 << 24) - 1) && "ChildCount out of bounds"); - assert(SourceColumnStart < (1 << 17) && "SourceColumnStart out of bounds"); - assert(SourceColumnEnd < (1 << 17) && "SourceColumnEnd out of bounds"); assert(AnnotationCount < (1 << 10) && "AnnotationCount out of bounds"); assert(AnnotationStart < ((1 << 20) - 1) && "AnnotationStart out of bounds"); - - assert(SourceLineStart < ((1 << 20) - 1) && - "SourceLineStart out of bounds"); } // For example if Enum, maps into Enums[LocalId] - uint32_t GetLocalId() const { - return LocalIdAnnotationSourceLineStart >> (64 - 24); - } - - uint32_t GetAnnotationStart() const { - return uint32_t(LocalIdAnnotationSourceLineStart << 24 >> (64 - 20)); - } - - uint32_t GetSourceLineStart() const { - return uint32_t(LocalIdAnnotationSourceLineStart & ((1 << 20) - 1)); - } + uint32_t GetLocalId() const { return LocalIdParentLo << 8 >> 8; } + uint32_t GetAnnotationStart() const { return AnnotationStartPad; } DxcHLSLNodeType GetNodeType() const { - return DxcHLSLNodeType(TypeChildsParentAnnotationsSourceColumnHi >> 60); + return DxcHLSLNodeType(ParentHiAnnotationsType >> 26); } // Includes recursive children - uint32_t GetChildCount() const { - return uint32_t(TypeChildsParentAnnotationsSourceColumnHi << 4 >> - (64 - 24)); - } + uint32_t GetChildCount() const { return ChildCountPad; } uint32_t GetAnnotationCount() const { - return uint32_t(TypeChildsParentAnnotationsSourceColumnHi << (4 + 24) >> - (64 - 10)); + return uint32_t(ParentHiAnnotationsType << 6 >> (32 - 10)); } uint32_t GetParentId() const { - return uint32_t(TypeChildsParentAnnotationsSourceColumnHi & - ((1 << 24) - 1)); - } - - uint32_t GetSourceColumnStart() const { - return SourceColumnStartLo | - ((TypeChildsParentAnnotationsSourceColumnHi & (1 << 24)) >> - (24 - 16)); - } - - uint32_t GetSourceColumnEnd() const { - return SourceColumnEndLo | - ((TypeChildsParentAnnotationsSourceColumnHi & (1 << 25)) >> - (25 - 16)); + return uint32_t(LocalIdParentLo >> 24) | uint32_t(ParentHiAnnotationsType << 16 >> 16); } void IncreaseChildCount() { - uint32_t childCount = GetChildCount(); - assert(childCount < ((1 << 24) - 1) && "Child count out of bounds"); - TypeChildsParentAnnotationsSourceColumnHi += uint64_t(1) << (10 + 2 + 24); + assert(ChildCountPad < ((1 << 24) - 1) && "Child count out of bounds"); + ++ChildCountPad; } bool operator==(const DxcHLSLNode &other) const { - return NameIdFileNameIdSourceLineCount == - other.NameIdFileNameIdSourceLineCount && - SourceColumnStartEndLo == other.SourceColumnStartEndLo && - TypeChildsParentAnnotationsSourceColumnHi == - other.TypeChildsParentAnnotationsSourceColumnHi && - LocalIdAnnotationSourceLineStart == - other.LocalIdAnnotationSourceLineStart; + return LocalIdParentLo == other.LocalIdParentLo && + ParentHiAnnotationsType == other.ParentHiAnnotationsType && + ChildCountPad == other.ChildCountPad; } }; @@ -1589,36 +1583,20 @@ struct DxcHLSLArray { uint32_t ArrayStart() const { return ArrayElemStart << 4 >> 4; } }; -struct DxcHLSLMember { - - uint32_t NameId; - uint32_t TypeId; - - bool operator==(const DxcHLSLMember &Other) const { - return Other.NameId == NameId && Other.TypeId == TypeId; - } -}; +using DxcHLSLMember = uint32_t; //typeId struct DxcHLSLType { // Almost maps to CShaderReflectionType and // D3D12_SHADER_TYPE_DESC, but tightly packed and // easily serializable union { struct { - uint32_t MembersCount; - uint32_t MembersStart; - }; - uint64_t MembersData; - }; - - union { - struct { - uint32_t NameId; // Can be empty + uint32_t MemberData; //24 : 8 (start, count) uint8_t Class; // D3D_SHADER_VARIABLE_CLASS uint8_t Type; // D3D_SHADER_VARIABLE_TYPE uint8_t Rows; uint8_t Columns; }; - uint64_t NameIdClassTypeRowsColums; + uint64_t MemberDataClassTypeRowsColums; }; union { @@ -1630,11 +1608,14 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and }; bool operator==(const DxcHLSLType &Other) const { - return Other.MembersData == MembersData && - NameIdClassTypeRowsColums == Other.NameIdClassTypeRowsColums && + return Other.MemberDataClassTypeRowsColums == + MemberDataClassTypeRowsColums && ElementsOrArrayIdBaseClass == Other.ElementsOrArrayIdBaseClass; } + uint32_t GetMemberCount() const { return MemberData >> 24; } + uint32_t GetMemberStart() const { return MemberData << 8 >> 8; } + bool IsMultiDimensionalArray() const { return ElementsOrArrayId >> 31; } bool IsArray() const { return ElementsOrArrayId; } bool Is1DArray() const { return IsArray() && !IsMultiDimensionalArray(); } @@ -1649,17 +1630,19 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and } DxcHLSLType() = default; - DxcHLSLType(uint32_t NameId, uint32_t BaseClass, uint32_t ElementsOrArrayId, + DxcHLSLType(uint32_t BaseClass, uint32_t ElementsOrArrayId, D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE Type, uint8_t Rows, uint8_t Columns, uint32_t MembersCount, uint32_t MembersStart) - : MembersStart(MembersStart), MembersCount(MembersCount), NameId(NameId), + : MemberData(MembersStart | (MembersCount << 24)), Class(Class), Type(Type), Rows(Rows), Columns(Columns), ElementsOrArrayId(ElementsOrArrayId), BaseClass(BaseClass) { assert(Class >= D3D_SVC_SCALAR && Class <= D3D_SVC_INTERFACE_POINTER && "Invalid class"); assert(Type >= D3D_SVT_VOID && Type <= D3D_SVT_UINT64 && "Invalid type"); + assert(MembersStart < (1 << 24) && "Member start out of bounds"); + assert(MembersCount < (1 << 8) && "Member count out of bounds"); } }; @@ -1689,10 +1672,13 @@ struct DxcReflectionData { std::vector Strings; std::unordered_map StringsToId; + std::vector StringsNonDebug; + std::unordered_map StringsToIdNonDebug; + std::vector Sources; std::unordered_map StringToSourceId; - std::vector Nodes; //0 = Root node (global scope) + std::vector Nodes; // 0 = Root node (global scope) std::vector Registers; std::vector Functions; @@ -1700,38 +1686,66 @@ struct DxcReflectionData { std::vector Enums; std::vector EnumValues; - //std::vector Parameters; + // std::vector Parameters; std::vector Annotations; std::vector Arrays; std::vector ArraySizes; - std::vector Members; + std::vector MemberTypeIds; std::vector Types; std::vector Buffers; + //Can be stripped if !(D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + + std::vector NodeSymbols; + std::vector MemberNameIds; + std::vector TypeNameIds; + void Dump(std::vector &Bytes) const; + void StripSymbols(); DxcReflectionData() = default; DxcReflectionData(const std::vector &Bytes); - bool operator==(const DxcReflectionData& other) const { - return Strings == other.Strings && Sources == other.Sources && - Nodes == other.Nodes && Registers == other.Registers && + bool operator==(const DxcReflectionData &other) const { + return Strings == other.Strings && + StringsNonDebug == other.StringsNonDebug && + Sources == other.Sources && Nodes == other.Nodes && + NodeSymbols == other.NodeSymbols && Registers == other.Registers && Functions == other.Functions && Enums == other.Enums && EnumValues == other.EnumValues && Annotations == other.Annotations && Arrays == other.Arrays && ArraySizes == other.ArraySizes && - Members == other.Members && Types == other.Types && + MemberTypeIds == other.MemberTypeIds && + MemberNameIds == other.MemberNameIds && + TypeNameIds == other.TypeNameIds && Types == other.Types && Buffers == other.Buffers; } }; static uint32_t RegisterString(DxcReflectionData &Refl, - const std::string &Name) { + const std::string &Name, bool isNonDebug) { - assert(Refl.Strings.size() < (uint32_t)-1 && "Strings overflow"); assert(Name.size() < 32768 && "Strings are limited to 32767"); + if (isNonDebug) { + + assert(Refl.StringsNonDebug.size() < (uint32_t)-1 && "Strings overflow"); + + auto it = Refl.StringsToIdNonDebug.find(Name); + + if (it != Refl.StringsToIdNonDebug.end()) + return it->second; + + uint32_t stringId = (uint32_t)Refl.StringsNonDebug.size(); + + Refl.StringsNonDebug.push_back(Name); + Refl.StringsToIdNonDebug[Name] = stringId; + return stringId; + } + + assert(Refl.Strings.size() < (uint32_t)-1 && "Strings overflow"); + auto it = Refl.StringsToId.find(Name); if (it != Refl.StringsToId.end()) @@ -1763,7 +1777,7 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, if (const AnnotateAttr *annotate = dyn_cast(attr)) { assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); Refl.Annotations.push_back( - RegisterString(Refl, annotate->getAnnotation().str())); + RegisterString(Refl, annotate->getAnnotation().str(), true)); assert(annotationCount != uint16_t(-1) && "Annotation count out of bounds"); ++annotationCount; @@ -1771,73 +1785,79 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, } } - uint16_t sourceLineCount = 0; - uint32_t sourceLineStart = 0; - uint32_t sourceColumnStart = 0; - uint32_t sourceColumnEnd = 0; + if (Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { - uint16_t fileNameId = (uint16_t)-1; + uint16_t sourceLineCount = 0; + uint32_t sourceLineStart = 0; + uint32_t sourceColumnStart = 0; + uint32_t sourceColumnEnd = 0; - SourceRange range = - Decl ? Decl->getSourceRange() : (Range ? *Range : SourceRange()); + uint16_t fileNameId = (uint16_t)-1; - SourceLocation start = range.getBegin(); - SourceLocation end = range.getEnd(); + SourceRange range = + Decl ? Decl->getSourceRange() : (Range ? *Range : SourceRange()); - if (start.isValid() && end.isValid()) { + SourceLocation start = range.getBegin(); + SourceLocation end = range.getEnd(); - PresumedLoc presumed = SM.getPresumedLoc(start); + if (start.isValid() && end.isValid()) { - SourceLocation realEnd = SM.getFileLoc(end); - SourceLocation endOfToken = - Lexer::getLocForEndOfToken(realEnd, 0, SM, LangOpts); - PresumedLoc presumedEnd = SM.getPresumedLoc(endOfToken); + PresumedLoc presumed = SM.getPresumedLoc(start); - if (presumed.isValid() && presumedEnd.isValid()) { + SourceLocation realEnd = SM.getFileLoc(end); + SourceLocation endOfToken = + Lexer::getLocForEndOfToken(realEnd, 0, SM, LangOpts); + PresumedLoc presumedEnd = SM.getPresumedLoc(endOfToken); - uint32_t startLine = presumed.getLine(); - uint32_t startCol = presumed.getColumn(); - uint32_t endLine = presumedEnd.getLine(); - uint32_t endCol = presumedEnd.getColumn(); + if (presumed.isValid() && presumedEnd.isValid()) { - std::string fileName = presumed.getFilename(); + uint32_t startLine = presumed.getLine(); + uint32_t startCol = presumed.getColumn(); + uint32_t endLine = presumedEnd.getLine(); + uint32_t endCol = presumedEnd.getColumn(); - assert(fileName == presumedEnd.getFilename() && - "End and start are not in the same file"); + std::string fileName = presumed.getFilename(); - auto it = Refl.StringToSourceId.find(fileName); - uint32_t i; + assert(fileName == presumedEnd.getFilename() && + "End and start are not in the same file"); - if (it == Refl.StringToSourceId.end()) { - i = (uint32_t)Refl.Sources.size(); - Refl.Sources.push_back(RegisterString(Refl, fileName)); - Refl.StringToSourceId[fileName] = i; - } + auto it = Refl.StringToSourceId.find(fileName); + uint32_t i; - else { - i = it->second; - } + if (it == Refl.StringToSourceId.end()) { + i = (uint32_t)Refl.Sources.size(); + Refl.Sources.push_back(RegisterString(Refl, fileName, false)); + Refl.StringToSourceId[fileName] = i; + } - assert(i < 65535 && "Source file count is limited to 16-bit"); - assert((endLine - startLine) < 65535 && - "Source line count is limited to 16-bit"); - assert(startLine < 1048576 && "Source line start is limited to 20-bit"); - assert(startCol < 131072 && "Column start is limited to 17-bit"); - assert(endCol < 131072 && "Column end is limited to 17-bit"); - - sourceLineCount = uint16_t(endLine - startLine + 1); - sourceLineStart = startLine; - sourceColumnStart = startCol; - sourceColumnEnd = endCol; - fileNameId = (uint16_t)i; + else { + i = it->second; + } + + assert(i < 65535 && "Source file count is limited to 16-bit"); + assert((endLine - startLine) < 65535 && + "Source line count is limited to 16-bit"); + assert(startLine < 1048576 && "Source line start is limited to 20-bit"); + assert(startCol < 131072 && "Column start is limited to 17-bit"); + assert(endCol < 131072 && "Column end is limited to 17-bit"); + + sourceLineCount = uint16_t(endLine - startLine + 1); + sourceLineStart = startLine; + sourceColumnStart = startCol; + sourceColumnEnd = endCol; + fileNameId = (uint16_t)i; + } } - } - uint32_t nameId = RegisterString(Refl, UnqualifiedName); + uint32_t nameId = RegisterString(Refl, UnqualifiedName, false); + + Refl.NodeSymbols.push_back( + DxcHLSLNodeSymbol(nameId, fileNameId, sourceLineCount, sourceLineStart, + sourceColumnStart, sourceColumnEnd)); + } - Refl.Nodes.push_back(DxcHLSLNode{nameId, Type, LocalId, annotationStart, fileNameId, - 0, ParentNodeId, sourceLineCount, sourceLineStart, - sourceColumnStart, sourceColumnEnd, annotationCount}); + Refl.Nodes.push_back(DxcHLSLNode{Type, LocalId, annotationStart, 0, + ParentNodeId, annotationCount}); uint32_t parentParent = ParentNodeId; @@ -2119,7 +2139,14 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, policy.AnonymousTagLocations = false; policy.SuppressTagKeyword = true; - uint32_t nameId = RegisterString(Refl, forName.getLocalUnqualifiedType().getAsString(policy)); + bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + uint32_t nameId = + hasSymbols + ? RegisterString( + Refl, forName.getLocalUnqualifiedType().getAsString(policy), + false) + : uint32_t(-1); + uint32_t arrayId = PushArray(Refl, arraySize, arrayElem); uint32_t elementsOrArrayId = 0; @@ -2255,15 +2282,21 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, QualType original = fieldDecl->getType(); std::string name = fieldDecl->getName(); - uint32_t nameId = RegisterString(Refl, name); + uint32_t nameId = hasSymbols ? RegisterString(Refl, name, false) : uint32_t(-1); uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); if (!membersCount) - membersOffset = (uint32_t) Refl.Members.size(); + membersOffset = (uint32_t) Refl.MemberTypeIds.size(); + + assert(Refl.MemberTypeIds.size() <= (uint32_t)-1 && + "Members out of bounds"); + + Refl.MemberTypeIds.push_back(typeId); + + if (hasSymbols) + Refl.MemberNameIds.push_back(nameId); - assert(Refl.Members.size() <= (uint32_t)-1 && "Members out of bounds"); - Refl.Members.push_back(DxcHLSLMember{nameId, typeId}); ++membersCount; } } @@ -2360,7 +2393,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, assert(Refl.Types.size() < (uint32_t)-1 && "Type id out of bounds"); - DxcHLSLType hlslType(nameId, baseClass, elementsOrArrayId, cls, type, rows, + DxcHLSLType hlslType(baseClass, elementsOrArrayId, cls, type, rows, columns, membersCount, membersOffset); uint32_t i = 0, j = (uint32_t)Refl.Types.size(); @@ -2369,8 +2402,13 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, if (Refl.Types[i] == hlslType) break; - if (i == j) + if (i == j) { + + if (hasSymbols) + Refl.TypeNameIds.push_back(nameId); + Refl.Types.push_back(hlslType); + } return i; } @@ -2612,6 +2650,15 @@ D3D12_HLSL_REFLECTION_FEATURE &operator|=(D3D12_HLSL_REFLECTION_FEATURE &a, return a = (D3D12_HLSL_REFLECTION_FEATURE)((uint32_t)a | (uint32_t)b); } +D3D12_HLSL_REFLECTION_FEATURE &operator&=(D3D12_HLSL_REFLECTION_FEATURE &a, + D3D12_HLSL_REFLECTION_FEATURE b) { + return a = (D3D12_HLSL_REFLECTION_FEATURE)((uint32_t)a & (uint32_t)b); +} + +D3D12_HLSL_REFLECTION_FEATURE operator~(D3D12_HLSL_REFLECTION_FEATURE a) { + return (D3D12_HLSL_REFLECTION_FEATURE)~(uint32_t)a; +} + static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, @@ -2878,11 +2925,15 @@ static void ReflectHLSL(ASTHelper &astHelper, DxcReflectionData& Refl, Refl = {}; Refl.Features = Features; - Refl.Strings.push_back(""); - Refl.StringsToId[""] = 0; - Refl.Nodes.push_back(DxcHLSLNode{0, DxcHLSLNodeType::Namespace, 0, 0, 0, 0, - 0xFFFF, 0, 0, 0, 0, 0}); + if (Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { + Refl.Strings.push_back(""); + Refl.StringsToId[""] = 0; + Refl.NodeSymbols.push_back(DxcHLSLNodeSymbol(0, 0, 0, 0, 0, 0)); + } + + Refl.Nodes.push_back( + DxcHLSLNode{DxcHLSLNodeType::Namespace, 0, 0, 0, 0xFFFF, 0}); RecursiveReflectHLSL(Ctx, astHelper.compiler.getASTContext(), Diags, SM, Refl, AutoBindingSpace, 0, Features, 0, DefaultRowMaj); @@ -3086,8 +3137,12 @@ std::string PrintTypeInfo(const DxcReflectionData &Refl, if (PreviousTypeName != underlyingTypeName && underlyingTypeName.size()) result += " (" + underlyingTypeName + ")"; - if (Type.BaseClass != (uint32_t)-1) - result += " : " + Refl.Strings[Refl.Types[Type.BaseClass].NameId]; + if (Type.BaseClass != (uint32_t)-1) { + bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + result += " : " + hasSymbols + ? Refl.Strings[Refl.TypeNameIds[Type.BaseClass]] + : "(unknown)"; + } return result; } @@ -3097,15 +3152,24 @@ void RecursePrintType(const DxcReflectionData &Refl, uint32_t TypeId, const DxcHLSLType &type = Refl.Types[TypeId]; - const std::string &name = Refl.Strings[type.NameId]; + bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + std::string name = hasSymbols ? Refl.Strings[Refl.TypeNameIds[TypeId]] + : GetBuiltinTypeName(Refl, type); + + if (name.empty() && !hasSymbols) + name = "(unknown)"; printf("%s%s%s%s\n", std::string(Depth, '\t').c_str(), Prefix, name.c_str(), PrintTypeInfo(Refl, type, name).c_str()); - for (uint32_t i = 0; i < type.MembersCount; ++i) { - const DxcHLSLMember &member = Refl.Members[type.MembersStart + i]; - std::string prefix = Refl.Strings[member.NameId] + ": "; - RecursePrintType(Refl, member.TypeId, Depth + 1, prefix.c_str()); + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { + + uint32_t memberId = type.GetMemberStart() + i; + std::string prefix = + (hasSymbols ? Refl.Strings[Refl.MemberNameIds[memberId]] : "(unknown)") + ": "; + + RecursePrintType(Refl, Refl.MemberTypeIds[memberId], Depth + 1, prefix.c_str()); } } @@ -3118,13 +3182,16 @@ uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, if (NodeId) { + bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + printf("%s%s %s\n", std::string(Depth - 1, '\t').c_str(), NodeTypeToString(node.GetNodeType()).c_str(), - Refl.Strings[node.NameId].c_str()); + hasSymbols ? Refl.Strings[Refl.NodeSymbols[NodeId].NameId].c_str() + : "(unknown)"); for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) printf("%s[[%s]]\n", std::string(Depth, '\t').c_str(), - Refl.Strings[Refl.Annotations[node.GetAnnotationStart() + i]] + Refl.StringsNonDebug[Refl.Annotations[node.GetAnnotationStart() + i]] .c_str()); uint32_t localId = node.GetLocalId(); @@ -3194,6 +3261,7 @@ struct DxcHLSLHeader { uint16_t Sources; D3D12_HLSL_REFLECTION_FEATURE Features; + uint32_t StringsNonDebug; uint32_t Strings; uint32_t Nodes; @@ -3370,31 +3438,43 @@ void Consume(const std::vector &Bytes, uint64_t &Offset, static constexpr uint32_t DxcReflectionDataMagic = DXC_FOURCC('D', 'H', 'R', 'D'); static constexpr uint16_t DxcReflectionDataVersion = 0; +void DxcReflectionData::StripSymbols() { + Strings.clear(); + Sources.clear(); + NodeSymbols.clear(); + TypeNameIds.clear(); + MemberNameIds.clear(); + Features &= ~D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; +} + void DxcReflectionData::Dump(std::vector &Bytes) const { uint64_t toReserve = sizeof(DxcHLSLHeader); - Advance(toReserve, Strings, Sources, Nodes, Registers, Functions, Enums, - EnumValues, Annotations, ArraySizes, Members, Types, Buffers); + Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, + Enums, EnumValues, Annotations, ArraySizes, MemberTypeIds, MemberNameIds, Types, TypeNameIds, Buffers); Bytes.resize(toReserve); toReserve = 0; UnsafeCast(Bytes, toReserve) = { - DxcReflectionDataMagic, DxcReflectionDataVersion, - uint16_t(Sources.size()), Features, uint32_t(Strings.size()), - uint32_t(Nodes.size()), uint32_t(Registers.size()), - uint32_t(Functions.size()), uint32_t(Enums.size()), - uint32_t(EnumValues.size()), uint32_t(Annotations.size()), - uint32_t(Arrays.size()), uint32_t(ArraySizes.size()), - uint32_t(Members.size()), uint32_t(Types.size()), + DxcReflectionDataMagic, DxcReflectionDataVersion, + uint16_t(Sources.size()), Features, + uint32_t(StringsNonDebug.size()), uint32_t(Strings.size()), + uint32_t(Nodes.size()), uint32_t(Registers.size()), + uint32_t(Functions.size()), uint32_t(Enums.size()), + uint32_t(EnumValues.size()), uint32_t(Annotations.size()), + uint32_t(Arrays.size()), uint32_t(ArraySizes.size()), + uint32_t(MemberTypeIds.size()), uint32_t(Types.size()), uint32_t(Buffers.size())}; toReserve += sizeof(DxcHLSLHeader); - Append(Bytes, toReserve, Strings, Sources, Nodes, Registers, Functions, Enums, EnumValues, Annotations, - ArraySizes, Members, Types, Buffers); + Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, + NodeSymbols, Registers, + Functions, Enums, EnumValues, Annotations, ArraySizes, MemberTypeIds, + MemberNameIds, Types, TypeNameIds, Buffers); } DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { @@ -3411,10 +3491,26 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { Features = header.Features; - Consume(Bytes, off, Strings, header.Strings, Sources, header.Sources, Nodes, header.Nodes, Registers, - header.Registers, Functions, header.Functions, Enums, header.Enums, - EnumValues, header.EnumValues, Annotations, header.Annotations, ArraySizes, header.ArraySizes, Members, - header.Members, Types, header.Types, Buffers, header.Buffers); + bool hasSymbolInfo = Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (!hasSymbolInfo && (header.Sources || header.Strings)) + throw std::invalid_argument("Sources are invalid without symbols"); + + uint32_t nodeSymbolCount = hasSymbolInfo ? header.Nodes : 0; + uint32_t memberSymbolCount = hasSymbolInfo ? header.Members : 0; + uint32_t typeSymbolCount = hasSymbolInfo ? header.Types : 0; + + Consume(Bytes, off, Strings, header.Strings, StringsNonDebug, + header.StringsNonDebug, Sources, header.Sources, Nodes, header.Nodes, + NodeSymbols, nodeSymbolCount, Registers, header.Registers, Functions, + header.Functions, Enums, header.Enums, EnumValues, header.EnumValues, + Annotations, header.Annotations, ArraySizes, header.ArraySizes, + MemberTypeIds, header.Members, MemberNameIds, memberSymbolCount, + Types, header.Types, TypeNameIds, typeSymbolCount, Buffers, + header.Buffers); + + if (off != Bytes.size()) + throw std::invalid_argument("Reflection info had unrecognized data on the back"); //Validation errors are throws to prevent accessing invalid data @@ -3426,9 +3522,13 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { const DxcHLSLNode &node = Nodes[i]; + if (hasSymbolInfo && (NodeSymbols[i].NameId >= header.Strings || + (NodeSymbols[i].FileNameId != uint16_t(-1) && + NodeSymbols[i].FileNameId >= header.Sources))) + throw std::invalid_argument("Node " + std::to_string(i) + + " points to invalid name or file name"); + if( - node.NameId >= header.Strings || - node.FileNameId >= header.Sources || node.GetAnnotationStart() + node.GetAnnotationCount() > header.Annotations || node.GetNodeType() > DxcHLSLNodeType::End || (i && node.GetParentId() >= i) || @@ -3559,17 +3659,8 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { " points to an invalid array element"); } - for (uint32_t i = 0; i < header.Members; ++i) { - - const DxcHLSLMember &mem = Members[i]; - - if (mem.NameId >= header.Strings || mem.TypeId >= header.Types) - throw std::invalid_argument("Member " + std::to_string(i) + - " points to an invalid string or type"); - } - for (uint32_t i = 0; i < header.Annotations; ++i) - if (Annotations[i] >= header.Strings) + if (Annotations[i] >= header.StringsNonDebug) throw std::invalid_argument("Annotation " + std::to_string(i) + " points to an invalid string"); @@ -3603,20 +3694,25 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { for (uint32_t i = 0; i < header.Members; ++i) { - const DxcHLSLMember &mem = Members[i]; + if (MemberTypeIds[i] >= header.Types) + throw std::invalid_argument("Member " + std::to_string(i) + + " points to an invalid type"); - if (mem.NameId >= header.Strings || mem.TypeId >= header.Types) + if (hasSymbolInfo && MemberNameIds[i] >= header.Strings) throw std::invalid_argument("Member " + std::to_string(i) + - " points to an invalid string or type"); + " points to an invalid string"); } for (uint32_t i = 0; i < header.Types; ++i) { const DxcHLSLType &type = Types[i]; - if (type.NameId >= header.Strings || - (type.BaseClass != uint32_t(-1) && type.BaseClass >= header.Types) || - (uint64_t)type.MembersStart + type.MembersCount > header.Members || + if (hasSymbolInfo && TypeNameIds[i] >= header.Strings) + throw std::invalid_argument("Type " + std::to_string(i) + + " points to an invalid string"); + + if ((type.BaseClass != uint32_t(-1) && type.BaseClass >= header.Types) || + type.GetMemberStart() + type.GetMemberCount() > header.Members || (type.ElementsOrArrayId >> 31 && (type.ElementsOrArrayId << 1 >> 1) >= header.Arrays)) throw std::invalid_argument( @@ -3679,7 +3775,7 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { case D3D_SVC_STRUCT: - if (!type.MembersCount) + if (!type.GetMemberCount()) throw std::invalid_argument("Type (struct) " + std::to_string(i) + " is missing children"); if (type.Type) @@ -3786,14 +3882,23 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, if(opts.RWOpt.ReflectHLSLVariables) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_VARIABLES; + if(!opts.RWOpt.ReflectHLSLDisableSymbols) + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + if (reflectMask) { + //Reflect + DxcReflectionData Refl; ReflectHLSL(astHelper, Refl, opts.AutoBindingSpace, reflectMask, opts.DefaultRowMajor); + //Print + RecursePrint(Refl, 0, 0, 0); + //Test serialization + std::vector bytes; Refl.Dump(bytes); @@ -3802,6 +3907,19 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, assert(Deserialized == Refl && "Dump or Deserialize doesn't match"); printf("Reflection size: %" PRIu64 "\n", bytes.size()); + + //Test stripping symbols + + Refl.StripSymbols(); + RecursePrint(Refl, 0, 0, 0); + + Refl.Dump(bytes); + + Deserialized = bytes; + + assert(Deserialized == Refl && "Dump or Deserialize doesn't match"); + + printf("Stripped reflection size: %" PRIu64 "\n", bytes.size()); } if (opts.RWOpt.SkipStatic && opts.RWOpt.SkipFunctionBody) { From 3598581c8839927bf0b56392d89c0ea0011c9269 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 31 Aug 2025 00:14:14 +0200 Subject: [PATCH 023/126] Added ability to compare two ASTs without checking debug data to check compatibility between two otherwise identical ASTs (except debug flag) --- .../clang/tools/libclang/dxcrewriteunused.cpp | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index e440c4f134..2398ff8fcd 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1708,18 +1708,21 @@ struct DxcReflectionData { DxcReflectionData() = default; DxcReflectionData(const std::vector &Bytes); + bool IsSameNonDebug(const DxcReflectionData &other) const { + return StringsNonDebug == other.StringsNonDebug && Nodes == other.Nodes && + Registers == other.Registers && Functions == other.Functions && + Enums == other.Enums && EnumValues == other.EnumValues && + Annotations == other.Annotations && Arrays == other.Arrays && + ArraySizes == other.ArraySizes && + MemberTypeIds == other.MemberTypeIds && Types == other.Types && + Buffers == other.Buffers; + } + bool operator==(const DxcReflectionData &other) const { - return Strings == other.Strings && - StringsNonDebug == other.StringsNonDebug && - Sources == other.Sources && Nodes == other.Nodes && - NodeSymbols == other.NodeSymbols && Registers == other.Registers && - Functions == other.Functions && Enums == other.Enums && - EnumValues == other.EnumValues && Annotations == other.Annotations && - Arrays == other.Arrays && ArraySizes == other.ArraySizes && - MemberTypeIds == other.MemberTypeIds && + return IsSameNonDebug(other) && Strings == other.Strings && + Sources == other.Sources && NodeSymbols == other.NodeSymbols && MemberNameIds == other.MemberNameIds && - TypeNameIds == other.TypeNameIds && Types == other.Types && - Buffers == other.Buffers; + TypeNameIds == other.TypeNameIds; } }; From 289ad18fc133d86ebf6140eead30af6601f2dbc9 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 31 Aug 2025 00:52:19 +0200 Subject: [PATCH 024/126] Added ability to generate 'fully resolved' member names and struct/function names. For example myNamespace::_buf.$Element.myType.a.b. This currently doesn't distinguish function/template overloading though. The use is for simple auto complete --- .../clang/tools/libclang/dxcrewriteunused.cpp | 111 ++++++++++++++++-- 1 file changed, 98 insertions(+), 13 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 2398ff8fcd..78ad81d154 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1702,11 +1702,16 @@ struct DxcReflectionData { std::vector MemberNameIds; std::vector TypeNameIds; + std::unordered_map FullyResolvedToNodeId; + std::vector NodeIdToFullyResolved; + std::unordered_map FullyResolvedToMemberId; + void Dump(std::vector &Bytes) const; void StripSymbols(); + bool GenerateNameLookupTable(); DxcReflectionData() = default; - DxcReflectionData(const std::vector &Bytes); + DxcReflectionData(const std::vector &Bytes, bool MakeNameLookupTable); bool IsSameNonDebug(const DxcReflectionData &other) const { return StringsNonDebug == other.StringsNonDebug && Nodes == other.Nodes && @@ -3443,13 +3448,89 @@ static constexpr uint16_t DxcReflectionDataVersion = 0; void DxcReflectionData::StripSymbols() { Strings.clear(); + StringsToId.clear(); Sources.clear(); + StringToSourceId.clear(); + FullyResolvedToNodeId.clear(); + NodeIdToFullyResolved.clear(); + FullyResolvedToMemberId.clear(); NodeSymbols.clear(); TypeNameIds.clear(); MemberNameIds.clear(); Features &= ~D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; } +void RecurseNameGenerationType(DxcReflectionData &Refl, uint32_t TypeId, + uint32_t LocalId, const std::string &Parent) { + + const DxcHLSLType &type = Refl.Types[TypeId]; + + if (type.Class == D3D_SVC_STRUCT) + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { + + uint32_t memberId = i + type.GetMemberStart(); + std::string memberName = + Parent + "." + Refl.Strings[Refl.MemberNameIds[memberId]]; + + Refl.FullyResolvedToMemberId[memberName] = memberId; + + RecurseNameGenerationType(Refl, Refl.MemberTypeIds[memberId], i, + memberName); + } +} + +uint32_t RecurseNameGeneration(DxcReflectionData &Refl, uint32_t NodeId, + uint32_t LocalId, const std::string &Parent, + bool IsDot) { + + const DxcHLSLNode &node = Refl.Nodes[NodeId]; + std::string self = Refl.Strings[Refl.NodeSymbols[NodeId].NameId]; + + if (self.empty() && NodeId) + self = std::to_string(LocalId); + + self = Parent.empty() ? self : Parent + (IsDot ? "." : "::") + self; + Refl.FullyResolvedToNodeId[self] = NodeId; + Refl.NodeIdToFullyResolved[NodeId] = self; + + bool isDotChild = node.GetNodeType() == DxcHLSLNodeType::Register; + bool isVar = node.GetNodeType() == DxcHLSLNodeType::Variable; + + for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) + i += RecurseNameGeneration(Refl, NodeId + 1 + i, j, self, isDotChild); + + if (isVar) { + + uint32_t typeId = node.GetLocalId(); + const DxcHLSLType &type = Refl.Types[typeId]; + + if (type.Class == D3D_SVC_STRUCT) + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { + + uint32_t memberId = i + type.GetMemberStart(); + std::string memberName = + self + "." + Refl.Strings[Refl.MemberNameIds[memberId]]; + + Refl.FullyResolvedToMemberId[memberName] = memberId; + + RecurseNameGenerationType(Refl, Refl.MemberTypeIds[memberId], i, + memberName); + } + } + + return node.GetChildCount(); +} + +bool DxcReflectionData::GenerateNameLookupTable() { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) || Nodes.empty()) + return false; + + NodeIdToFullyResolved.resize(Nodes.size()); + RecurseNameGeneration(*this, 0, 0, "", false); + return true; +} + void DxcReflectionData::Dump(std::vector &Bytes) const { uint64_t toReserve = sizeof(DxcHLSLHeader); @@ -3480,7 +3561,8 @@ void DxcReflectionData::Dump(std::vector &Bytes) const { MemberNameIds, Types, TypeNameIds, Buffers); } -DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { +DxcReflectionData::DxcReflectionData(const std::vector &Bytes, + bool MakeNameLookupTable) { uint64_t off = 0; DxcHLSLHeader header; @@ -3842,6 +3924,9 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes) { " has an invalid class"); } } + + if (MakeNameLookupTable) + GenerateNameLookupTable(); }; static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, @@ -3892,35 +3977,35 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, //Reflect - DxcReflectionData Refl; - ReflectHLSL(astHelper, Refl, opts.AutoBindingSpace, reflectMask, + DxcReflectionData refl; + ReflectHLSL(astHelper, refl, opts.AutoBindingSpace, reflectMask, opts.DefaultRowMajor); //Print - RecursePrint(Refl, 0, 0, 0); + RecursePrint(refl, 0, 0, 0); //Test serialization std::vector bytes; - Refl.Dump(bytes); + refl.Dump(bytes); - DxcReflectionData Deserialized(bytes); + DxcReflectionData deserialized(bytes, true); - assert(Deserialized == Refl && "Dump or Deserialize doesn't match"); + assert(deserialized == refl && "Dump or Deserialize doesn't match"); printf("Reflection size: %" PRIu64 "\n", bytes.size()); //Test stripping symbols - Refl.StripSymbols(); - RecursePrint(Refl, 0, 0, 0); + refl.StripSymbols(); + RecursePrint(refl, 0, 0, 0); - Refl.Dump(bytes); + refl.Dump(bytes); - Deserialized = bytes; + deserialized = DxcReflectionData(bytes, false); - assert(Deserialized == Refl && "Dump or Deserialize doesn't match"); + assert(deserialized == refl && "Dump or Deserialize doesn't match"); printf("Stripped reflection size: %" PRIu64 "\n", bytes.size()); } From 693d3b7127de635dbed7b2bfce8027339283e6a1 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 31 Aug 2025 12:42:50 +0200 Subject: [PATCH 025/126] Added support for inheritance and annotations can now either be 'builtin' or non builtin. 'builtin' currently only supports the shader annotation, since others might contain more complex syntax that is easier to handle at IL level --- .../clang/tools/libclang/dxcrewriteunused.cpp | 103 ++++++++++++++---- 1 file changed, 84 insertions(+), 19 deletions(-) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 78ad81d154..0bf8ccdea5 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1665,6 +1665,28 @@ struct DxcHLSLBuffer { // Almost maps to CShaderReflectionConstantBuffer and } }; +struct DxcHLSLAnnotation { + + uint32_t StringNonDebugAndIsBuiltin; + + DxcHLSLAnnotation() = default; + + DxcHLSLAnnotation(uint32_t StringNonDebug, bool IsBuiltin) + : StringNonDebugAndIsBuiltin(StringNonDebug | + (IsBuiltin ? (1u << 31) : 0)) { + assert(StringNonDebug < (1u << 31) && "String non debug out of bounds"); + } + + bool operator==(const DxcHLSLAnnotation &other) const { + return StringNonDebugAndIsBuiltin == other.StringNonDebugAndIsBuiltin; + } + + bool GetIsBuiltin() const { return StringNonDebugAndIsBuiltin >> 31; } + uint32_t GetStringNonDebug() const { + return StringNonDebugAndIsBuiltin << 1 >> 1; + } +}; + struct DxcReflectionData { D3D12_HLSL_REFLECTION_FEATURE Features; @@ -1687,7 +1709,7 @@ struct DxcReflectionData { std::vector EnumValues; // std::vector Parameters; - std::vector Annotations; + std::vector Annotations; std::vector Arrays; std::vector ArraySizes; @@ -1783,9 +1805,27 @@ static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, if (Decl) { for (const Attr *attr : Decl->attrs()) { if (const AnnotateAttr *annotate = dyn_cast(attr)) { + + assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); + + Refl.Annotations.push_back(DxcHLSLAnnotation( + RegisterString(Refl, annotate->getAnnotation().str(), true), + false)); + + assert(annotationCount != uint16_t(-1) && + "Annotation count out of bounds"); + ++annotationCount; + + } else if (const HLSLShaderAttr *shaderAttr = + dyn_cast(attr)) { + assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); - Refl.Annotations.push_back( - RegisterString(Refl, annotate->getAnnotation().str(), true)); + + Refl.Annotations.push_back(DxcHLSLAnnotation( + RegisterString( + Refl, "shader(\"" + shaderAttr->getStage().str() + "\")", true), + true)); + assert(annotationCount != uint16_t(-1) && "Annotation count out of bounds"); ++annotationCount; @@ -2165,6 +2205,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, elementsOrArrayId = arraySize > 1 ? arraySize : 0; //Unwrap vector and matrix + //And base type D3D_SHADER_VARIABLE_CLASS cls = D3D_SVC_STRUCT; uint8_t rows = 0, columns = 0; @@ -2172,6 +2213,8 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, uint32_t membersCount = 0; uint32_t membersOffset = 0; + uint32_t baseType = uint32_t(-1); + if (const RecordType *record = underlying->getAs()) { bool standardType = false; @@ -2278,6 +2321,28 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, if (!standardType && recordDecl->isCompleteDefinition()) { + //Base types + + if (CXXRecordDecl *cxxRecordDecl = dyn_cast(recordDecl)) + if (cxxRecordDecl->getNumBases()) { + for (auto &I : cxxRecordDecl->bases()) { + + QualType qualType = I.getType(); + CXXRecordDecl *BaseDecl = + cast(qualType->castAs()->getDecl()); + + if (BaseDecl->isInterface()) + continue; + + assert(baseType == uint32_t(-1) && + "Multiple base types isn't supported in HLSL"); + + baseType = GenerateTypeInfo(ASTCtx, Refl, qualType, DefaultRowMaj); + } + } + + //Inner types + for (Decl *decl : recordDecl->decls()) { // TODO: We could query other types VarDecl @@ -2395,13 +2460,11 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, } } - //TODO: Base class - - uint32_t baseClass = (uint32_t) -1; + //Insert assert(Refl.Types.size() < (uint32_t)-1 && "Type id out of bounds"); - DxcHLSLType hlslType(baseClass, elementsOrArrayId, cls, type, rows, + DxcHLSLType hlslType(baseType, elementsOrArrayId, cls, type, rows, columns, membersCount, membersOffset); uint32_t i = 0, j = (uint32_t)Refl.Types.size(); @@ -3145,13 +3208,6 @@ std::string PrintTypeInfo(const DxcReflectionData &Refl, if (PreviousTypeName != underlyingTypeName && underlyingTypeName.size()) result += " (" + underlyingTypeName + ")"; - if (Type.BaseClass != (uint32_t)-1) { - bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - result += " : " + hasSymbols - ? Refl.Strings[Refl.TypeNameIds[Type.BaseClass]] - : "(unknown)"; - } - return result; } @@ -3171,6 +3227,9 @@ void RecursePrintType(const DxcReflectionData &Refl, uint32_t TypeId, printf("%s%s%s%s\n", std::string(Depth, '\t').c_str(), Prefix, name.c_str(), PrintTypeInfo(Refl, type, name).c_str()); + if (type.BaseClass != uint32_t(-1)) + RecursePrintType(Refl, type.BaseClass, Depth + 1, Prefix); + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { uint32_t memberId = type.GetMemberStart() + i; @@ -3197,10 +3256,16 @@ uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, hasSymbols ? Refl.Strings[Refl.NodeSymbols[NodeId].NameId].c_str() : "(unknown)"); - for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) - printf("%s[[%s]]\n", std::string(Depth, '\t').c_str(), - Refl.StringsNonDebug[Refl.Annotations[node.GetAnnotationStart() + i]] - .c_str()); + for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) { + + const DxcHLSLAnnotation &annotation = + Refl.Annotations[node.GetAnnotationStart() + i]; + + printf(annotation.GetIsBuiltin() ? "%s[%s]\n" : "%s[[%s]]\n", + std::string(Depth, '\t').c_str(), + Refl.StringsNonDebug[annotation.GetStringNonDebug()] + .c_str()); + } uint32_t localId = node.GetLocalId(); @@ -3745,7 +3810,7 @@ DxcReflectionData::DxcReflectionData(const std::vector &Bytes, } for (uint32_t i = 0; i < header.Annotations; ++i) - if (Annotations[i] >= header.StringsNonDebug) + if (Annotations[i].GetStringNonDebug() >= header.StringsNonDebug) throw std::invalid_argument("Annotation " + std::to_string(i) + " points to an invalid string"); From 884d43b2864cfdc7ca6b790c7a94f27be327c7d0 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 31 Aug 2025 18:24:59 +0200 Subject: [PATCH 026/126] Refactored to put reflection logic into a standalone library. Fixed an issue with textures with scalars. --- include/dxc/DxcReflection/DxcReflection.h | 510 +++ include/dxc/dxctools.h | 16 + tools/clang/tools/CMakeLists.txt | 1 + .../clang/tools/dxcreflection/CMakeLists.txt | 12 + .../tools/dxcreflection/DxcReflection.cpp | 2251 ++++++++++++++ tools/clang/tools/libclang/CMakeLists.txt | 1 + .../clang/tools/libclang/dxcrewriteunused.cpp | 2742 +---------------- 7 files changed, 2811 insertions(+), 2722 deletions(-) create mode 100644 include/dxc/DxcReflection/DxcReflection.h create mode 100644 tools/clang/tools/dxcreflection/CMakeLists.txt create mode 100644 tools/clang/tools/dxcreflection/DxcReflection.cpp diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h new file mode 100644 index 0000000000..00e9bd3b39 --- /dev/null +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -0,0 +1,510 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// DxcReflection.h // +// Copyright (C) Microsoft Corporation. All rights reserved. // +// This file is distributed under the University of Illinois Open Source // +// License. See LICENSE.TXT for details. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +#include + +#include "d3d12shader.h" +#include "dxc/dxctools.h" + +namespace clang { +class TranslationUnitDecl; +class CompilerInstance; +} + +#pragma warning(disable : 4201) + +namespace hlsl { + +enum class DxcHLSLNodeType : uint64_t { + + Register, + Function, + Enum, + EnumValue, + Namespace, + Typedef, + Using, + Variable, //localId points to the type for a variable + //Parameter, + + Start = Register, + End = Variable +}; + +struct DxcHLSLNode { + + uint32_t LocalIdParentLo; //24 : 8 + uint32_t ParentHiAnnotationsType; //16 : 10 : 6 + uint32_t ChildCountPad; //24 : 8 + uint32_t AnnotationStartPad; //20 : 12 + + DxcHLSLNode() = default; + + DxcHLSLNode(DxcHLSLNodeType NodeType, uint32_t LocalId, + uint32_t AnnotationStart, uint32_t ChildCount, uint32_t ParentId, + uint16_t AnnotationCount) + : LocalIdParentLo(LocalId | (ParentId << 24)), + ChildCountPad(ChildCount), + AnnotationStartPad(AnnotationStart), + ParentHiAnnotationsType( + (uint32_t(NodeType) << 26) | + (uint32_t(AnnotationCount) << 16) | + (ParentId >> 8)) { + + assert(NodeType >= DxcHLSLNodeType::Start && + NodeType <= DxcHLSLNodeType::End && "Invalid enum value"); + + assert(LocalId < ((1 << 24) - 1) && "LocalId out of bounds"); + assert(ParentId < ((1 << 24) - 1) && "ParentId out of bounds"); + assert(ChildCount < ((1 << 24) - 1) && "ChildCount out of bounds"); + assert(AnnotationCount < (1 << 10) && "AnnotationCount out of bounds"); + + assert(AnnotationStart < ((1 << 20) - 1) && + "AnnotationStart out of bounds"); + } + + // For example if Enum, maps into Enums[LocalId] + uint32_t GetLocalId() const { return LocalIdParentLo << 8 >> 8; } + uint32_t GetAnnotationStart() const { return AnnotationStartPad; } + + DxcHLSLNodeType GetNodeType() const { + return DxcHLSLNodeType(ParentHiAnnotationsType >> 26); + } + + // Includes recursive children + uint32_t GetChildCount() const { return ChildCountPad; } + + uint32_t GetAnnotationCount() const { + return uint32_t(ParentHiAnnotationsType << 6 >> (32 - 10)); + } + + uint32_t GetParentId() const { + return uint32_t(LocalIdParentLo >> 24) | uint32_t(ParentHiAnnotationsType << 16 >> 8); + } + + void IncreaseChildCount() { + assert(ChildCountPad < ((1 << 24) - 1) && "Child count out of bounds"); + ++ChildCountPad; + } + + bool operator==(const DxcHLSLNode &other) const { + return LocalIdParentLo == other.LocalIdParentLo && + ParentHiAnnotationsType == other.ParentHiAnnotationsType && + ChildCountPad == other.ChildCountPad; + } +}; + +struct DxcHLSLNodeSymbol { + + union { + struct { + uint32_t NameId; // Local name (not including parent's name) + + uint16_t FileNameId; //-1 == no file info + uint16_t SourceLineCount; + }; + uint64_t NameIdFileNameIdSourceLineCount; + }; + + union { + struct { + uint16_t SourceColumnStartLo; + uint16_t SourceColumnEndLo; + uint32_t ColumnHiSourceLinePad; // 2 : 20 : 10 + }; + uint64_t SourceColumnStartEndLo; + }; + + DxcHLSLNodeSymbol() = default; + + DxcHLSLNodeSymbol(uint32_t NameId, uint16_t FileNameId, + uint16_t SourceLineCount, uint32_t SourceLineStart, + uint32_t SourceColumnStart, uint32_t SourceColumnEnd) + : NameId(NameId), FileNameId(FileNameId), + SourceLineCount(SourceLineCount), + SourceColumnStartLo(uint16_t(SourceColumnStart)), + SourceColumnEndLo(uint16_t(SourceColumnEnd)), + ColumnHiSourceLinePad((SourceColumnStart >> 16) | + (SourceColumnEnd >> 16 << 1) | + (SourceLineStart << 2)) { + + assert(SourceColumnStart < (1 << 17) && "SourceColumnStart out of bounds"); + assert(SourceColumnEnd < (1 << 17) && "SourceColumnEnd out of bounds"); + + assert(SourceLineStart < ((1 << 20) - 1) && + "SourceLineStart out of bounds"); + } + + uint32_t GetSourceLineStart() const { + return uint32_t(ColumnHiSourceLinePad >> 2); + } + + uint32_t GetSourceColumnStart() const { + return SourceColumnStartLo | ((ColumnHiSourceLinePad & 1) << 16); + } + + uint32_t GetSourceColumnEnd() const { + return SourceColumnEndLo | ((ColumnHiSourceLinePad & 2) << 15); + } + + bool operator==(const DxcHLSLNodeSymbol &other) const { + return NameIdFileNameIdSourceLineCount == + other.NameIdFileNameIdSourceLineCount && + SourceColumnStartEndLo == other.SourceColumnStartEndLo; + } +}; + +struct DxcHLSLEnumDesc { + + uint32_t NodeId; + D3D12_HLSL_ENUM_TYPE Type; + + bool operator==(const DxcHLSLEnumDesc &other) const { + return NodeId == other.NodeId && Type == other.Type; + } +}; + +struct DxcHLSLEnumValue { + + int64_t Value; + uint32_t NodeId; + + bool operator==(const DxcHLSLEnumValue &other) const { + return Value == other.Value && + NodeId == other.NodeId; + } +}; + +/* +struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC (ex. + // First(In/Out)(Register/Component)), but with + // std::string and NodeId + + std::string SemanticName; + D3D_SHADER_VARIABLE_TYPE Type; // Element type. + D3D_SHADER_VARIABLE_CLASS Class; // Scalar/Vector/Matrix. + uint32_t Rows; // Rows are for matrix parameters. + uint32_t Columns; // Components or Columns in matrix. + D3D_INTERPOLATION_MODE InterpolationMode; // Interpolation mode. + D3D_PARAMETER_FLAGS Flags; // Parameter modifiers. + uint32_t NodeId; + + // TODO: Array info +};*/ + +struct DxcHLSLFunction { + + uint32_t NodeId; + uint32_t NumParametersHasReturnAndDefinition; + + DxcHLSLFunction() = default; + + DxcHLSLFunction(uint32_t NodeId, uint32_t NumParameters, bool HasReturn, + bool HasDefinition) + : NodeId(NodeId), + NumParametersHasReturnAndDefinition(NumParameters | + (HasReturn ? (1 << 30) : 0) | + (HasDefinition ? (1 << 31) : 0)) { + + assert(NumParameters < (1 << 30) && "NumParameters out of bounds"); + } + + uint32_t GetNumParameters() const { + return NumParametersHasReturnAndDefinition << 2 >> 2; + } + + bool HasReturn() const { + return (NumParametersHasReturnAndDefinition >> 30) & 1; + } + + bool HasDefinition() const { + return (NumParametersHasReturnAndDefinition >> 31) & 1; + } + + bool operator==(const DxcHLSLFunction &other) const { + return NodeId == other.NodeId && + NumParametersHasReturnAndDefinition == + other.NumParametersHasReturnAndDefinition; + } +}; + +struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus + // the Name (and uID replaced with NodeID) and added + // arrayIndex and better packing + + union { + struct { + uint8_t Type; // D3D_SHADER_INPUT_TYPE + uint8_t Dimension; // D3D_SRV_DIMENSION + uint8_t ReturnType; // D3D_RESOURCE_RETURN_TYPE + uint8_t uFlags; + + uint32_t BindPoint; + }; + uint64_t TypeDimensionReturnTypeFlagsBindPoint; + }; + + union { + struct { + uint32_t Space; + uint32_t BindCount; + }; + uint64_t SpaceBindCount; + }; + + union { + struct { + uint32_t NumSamples; + uint32_t NodeId; + }; + uint64_t NumSamplesNodeId; + }; + + union { + struct { + uint32_t ArrayId; // Only if BindCount > 1 and the array is 2D+ (else -1) + uint32_t BufferId; // If cbuffer or structured buffer + }; + uint64_t ArrayIdBufferId; + }; + + DxcHLSLRegister() = default; + DxcHLSLRegister(D3D_SHADER_INPUT_TYPE Type, uint32_t BindPoint, + uint32_t BindCount, uint32_t uFlags, + D3D_RESOURCE_RETURN_TYPE ReturnType, + D3D_SRV_DIMENSION Dimension, uint32_t NumSamples, + uint32_t Space, uint32_t NodeId, uint32_t ArrayId, + uint32_t BufferId) + : Type(Type), BindPoint(BindPoint), BindCount(BindCount), uFlags(uFlags), + ReturnType(ReturnType), Dimension(Dimension), + NumSamples(NumSamples), Space(Space), NodeId(NodeId), + ArrayId(ArrayId), BufferId(BufferId) { + + assert(Type >= D3D_SIT_CBUFFER && Type <= D3D_SIT_UAV_FEEDBACKTEXTURE && + "Invalid type"); + + assert(ReturnType >= 0 && ReturnType <= D3D_RETURN_TYPE_CONTINUED && + "Invalid return type"); + + assert(Dimension >= D3D_SRV_DIMENSION_UNKNOWN && + Dimension <= D3D_SRV_DIMENSION_BUFFEREX && "Invalid srv dimension"); + + assert(!(uFlags >> 8) && "Invalid user flags"); + } + + bool operator==(const DxcHLSLRegister &other) const { + return TypeDimensionReturnTypeFlagsBindPoint == + other.TypeDimensionReturnTypeFlagsBindPoint && + SpaceBindCount == other.SpaceBindCount && + NumSamplesNodeId == other.NumSamplesNodeId && + ArrayIdBufferId == other.ArrayIdBufferId; + } +}; + +struct DxcHLSLArray { + + uint32_t ArrayElemStart; + + DxcHLSLArray() = default; + DxcHLSLArray(uint32_t ArrayElem, uint32_t ArrayStart) + : ArrayElemStart((ArrayElem << 28) | ArrayStart) { + + assert(ArrayElem <= 8 && ArrayElem > 1 && "ArrayElem out of bounds"); + assert(ArrayStart < (1 << 28) && "ArrayStart out of bounds"); + } + + bool operator==(const DxcHLSLArray &Other) const { + return Other.ArrayElemStart == ArrayElemStart; + } + + uint32_t ArrayElem() const { return ArrayElemStart >> 28; } + uint32_t ArrayStart() const { return ArrayElemStart << 4 >> 4; } +}; + +using DxcHLSLMember = uint32_t; //typeId + +struct DxcHLSLType { // Almost maps to CShaderReflectionType and + // D3D12_SHADER_TYPE_DESC, but tightly packed and + // easily serializable + union { + struct { + uint32_t MemberData; //24 : 8 (start, count) + uint8_t Class; // D3D_SHADER_VARIABLE_CLASS + uint8_t Type; // D3D_SHADER_VARIABLE_TYPE + uint8_t Rows; + uint8_t Columns; + }; + uint64_t MemberDataClassTypeRowsColums; + }; + + union { + struct { + uint32_t ElementsOrArrayId; + uint32_t BaseClass; // -1 if none, otherwise a type index + }; + uint64_t ElementsOrArrayIdBaseClass; + }; + + bool operator==(const DxcHLSLType &Other) const { + return Other.MemberDataClassTypeRowsColums == + MemberDataClassTypeRowsColums && + ElementsOrArrayIdBaseClass == Other.ElementsOrArrayIdBaseClass; + } + + uint32_t GetMemberCount() const { return MemberData >> 24; } + uint32_t GetMemberStart() const { return MemberData << 8 >> 8; } + + bool IsMultiDimensionalArray() const { return ElementsOrArrayId >> 31; } + bool IsArray() const { return ElementsOrArrayId; } + bool Is1DArray() const { return IsArray() && !IsMultiDimensionalArray(); } + + uint32_t Get1DElements() const { + return IsMultiDimensionalArray() ? 0 : ElementsOrArrayId; + } + + uint32_t GetMultiDimensionalArrayId() const { + return IsMultiDimensionalArray() ? (ElementsOrArrayId << 1 >> 1) + : (uint32_t)-1; + } + + DxcHLSLType() = default; + DxcHLSLType(uint32_t BaseClass, uint32_t ElementsOrArrayId, + D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE Type, + uint8_t Rows, uint8_t Columns, uint32_t MembersCount, + uint32_t MembersStart) + : MemberData(MembersStart | (MembersCount << 24)), + Class(Class), Type(Type), Rows(Rows), Columns(Columns), + ElementsOrArrayId(ElementsOrArrayId), BaseClass(BaseClass) { + + assert(Class >= D3D_SVC_SCALAR && Class <= D3D_SVC_INTERFACE_POINTER && + "Invalid class"); + assert(Type >= D3D_SVT_VOID && Type <= D3D_SVT_UINT64 && "Invalid type"); + assert(MembersStart < (1 << 24) && "Member start out of bounds"); + assert(MembersCount < (1 << 8) && "Member count out of bounds"); + } +}; + +struct DxcHLSLBuffer { // Almost maps to CShaderReflectionConstantBuffer and + // D3D12_SHADER_BUFFER_DESC + + D3D_CBUFFER_TYPE Type; + uint32_t NodeId; + + bool operator==(const DxcHLSLBuffer &other) const { + return Type == other.Type && NodeId == other.NodeId; + } +}; + +struct DxcHLSLAnnotation { + + uint32_t StringNonDebugAndIsBuiltin; + + DxcHLSLAnnotation() = default; + + DxcHLSLAnnotation(uint32_t StringNonDebug, bool IsBuiltin) + : StringNonDebugAndIsBuiltin(StringNonDebug | + (IsBuiltin ? (1u << 31) : 0)) { + assert(StringNonDebug < (1u << 31) && "String non debug out of bounds"); + } + + bool operator==(const DxcHLSLAnnotation &other) const { + return StringNonDebugAndIsBuiltin == other.StringNonDebugAndIsBuiltin; + } + + bool GetIsBuiltin() const { return StringNonDebugAndIsBuiltin >> 31; } + + uint32_t GetStringNonDebug() const { + return StringNonDebugAndIsBuiltin << 1 >> 1; + } +}; + +struct DxcHLSLReflection { + + D3D12_HLSL_REFLECTION_FEATURE Features; + + std::vector Strings; + std::unordered_map StringsToId; + + std::vector StringsNonDebug; + std::unordered_map StringsToIdNonDebug; + + std::vector Sources; + std::unordered_map StringToSourceId; + + std::vector Nodes; // 0 = Root node (global scope) + + std::vector Registers; + std::vector Functions; + + std::vector Enums; + std::vector EnumValues; + + // std::vector Parameters; + std::vector Annotations; + + std::vector Arrays; + std::vector ArraySizes; + + std::vector MemberTypeIds; + std::vector Types; + std::vector Buffers; + + // Can be stripped if !(D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + + std::vector NodeSymbols; + std::vector MemberNameIds; + std::vector TypeNameIds; + + // Only generated if deserialized with MakeNameLookupTable or + // GenerateNameLookupTable is called (and if symbols aren't stripped) + + std::unordered_map FullyResolvedToNodeId; + std::vector NodeIdToFullyResolved; + std::unordered_map FullyResolvedToMemberId; + + void Dump(std::vector &Bytes) const; + void Printf() const; + void StripSymbols(); + bool GenerateNameLookupTable(); + + DxcHLSLReflection() = default; + DxcHLSLReflection(const std::vector &Bytes, + bool MakeNameLookupTable); + + DxcHLSLReflection(clang::CompilerInstance &Compiler, + clang::TranslationUnitDecl &Ctx, + uint32_t AutoBindingSpace, + D3D12_HLSL_REFLECTION_FEATURE Features, bool DefaultRowMaj); + + bool IsSameNonDebug(const DxcHLSLReflection &other) const { + return StringsNonDebug == other.StringsNonDebug && Nodes == other.Nodes && + Registers == other.Registers && Functions == other.Functions && + Enums == other.Enums && EnumValues == other.EnumValues && + Annotations == other.Annotations && Arrays == other.Arrays && + ArraySizes == other.ArraySizes && + MemberTypeIds == other.MemberTypeIds && Types == other.Types && + Buffers == other.Buffers; + } + + bool operator==(const DxcHLSLReflection &other) const { + return IsSameNonDebug(other) && Strings == other.Strings && + Sources == other.Sources && NodeSymbols == other.NodeSymbols && + MemberNameIds == other.MemberNameIds && + TypeNameIds == other.TypeNameIds; + } +}; + +} // namespace hlsl + +#pragma warning(default : 4201) diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 5c2cdf7dfa..dd4e3abb59 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -99,6 +99,22 @@ enum D3D12_HLSL_REFLECTION_FEATURE { D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO = 1 << 6 }; +inline D3D12_HLSL_REFLECTION_FEATURE &operator|=(D3D12_HLSL_REFLECTION_FEATURE &a, + D3D12_HLSL_REFLECTION_FEATURE b) { + return a = (D3D12_HLSL_REFLECTION_FEATURE)((uint32_t)a | (uint32_t)b); +} + +inline D3D12_HLSL_REFLECTION_FEATURE & +operator&=(D3D12_HLSL_REFLECTION_FEATURE &a, + D3D12_HLSL_REFLECTION_FEATURE b) { + return a = (D3D12_HLSL_REFLECTION_FEATURE)((uint32_t)a & (uint32_t)b); +} + +inline D3D12_HLSL_REFLECTION_FEATURE +operator~(D3D12_HLSL_REFLECTION_FEATURE a) { + return (D3D12_HLSL_REFLECTION_FEATURE) ~(uint32_t)a; +} + struct D3D12_HLSL_REFLECTION_DESC { D3D12_HLSL_REFLECTION_FEATURE Features; UINT ConstantBufferCount; diff --git a/tools/clang/tools/CMakeLists.txt b/tools/clang/tools/CMakeLists.txt index 9991de0308..97e4a8d297 100644 --- a/tools/clang/tools/CMakeLists.txt +++ b/tools/clang/tools/CMakeLists.txt @@ -4,6 +4,7 @@ add_subdirectory(driver) # add_subdirectory(clang-fuzzer) # HLSL Change # add_subdirectory(c-index-test) # HLSL Change +add_subdirectory(dxcreflection) # HLSL Change add_subdirectory(libclang) if(0 AND CLANG_ENABLE_ARCMT) # HLSL Change diff --git a/tools/clang/tools/dxcreflection/CMakeLists.txt b/tools/clang/tools/dxcreflection/CMakeLists.txt new file mode 100644 index 0000000000..b6820d83ba --- /dev/null +++ b/tools/clang/tools/dxcreflection/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (C) Microsoft Corporation. All rights reserved. +# This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. + +set(LIBRARIES + clangFrontend + clangAST + clangBasic + clangLex + ) + +add_clang_library(dxcreflection STATIC DxcReflection.cpp) +target_link_libraries(dxcreflection PRIVATE ${LIBRARIES}) diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp new file mode 100644 index 0000000000..94b36a9a1f --- /dev/null +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -0,0 +1,2251 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// DxcReflection.cpp // +// Copyright (C) Microsoft Corporation. All rights reserved. // +// This file is distributed under the University of Illinois Open Source // +// License. See LICENSE.TXT for details. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include "clang/AST/Attr.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/HlslTypes.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/basic/SourceManager.h" +#include "clang/Lex/Lexer.h" +#include "dxc/DxcReflection/DxcReflection.h" + +#undef min +#undef max + +using namespace clang; + +namespace hlsl { + +struct DxcRegisterTypeInfo { + D3D_SHADER_INPUT_TYPE RegisterType; + D3D_SHADER_INPUT_FLAGS RegisterFlags; + D3D_SRV_DIMENSION TextureDimension; + D3D_RESOURCE_RETURN_TYPE TextureValue; + uint32_t SampleCount; +}; + +static uint32_t RegisterString(DxcHLSLReflection &Refl, + const std::string &Name, bool isNonDebug) { + + assert(Name.size() < 32768 && "Strings are limited to 32767"); + + if (isNonDebug) { + + assert(Refl.StringsNonDebug.size() < (uint32_t)-1 && "Strings overflow"); + + auto it = Refl.StringsToIdNonDebug.find(Name); + + if (it != Refl.StringsToIdNonDebug.end()) + return it->second; + + uint32_t stringId = (uint32_t)Refl.StringsNonDebug.size(); + + Refl.StringsNonDebug.push_back(Name); + Refl.StringsToIdNonDebug[Name] = stringId; + return stringId; + } + + assert(Refl.Strings.size() < (uint32_t)-1 && "Strings overflow"); + + auto it = Refl.StringsToId.find(Name); + + if (it != Refl.StringsToId.end()) + return it->second; + + uint32_t stringId = (uint32_t) Refl.Strings.size(); + + Refl.Strings.push_back(Name); + Refl.StringsToId[Name] = stringId; + return stringId; +} + +static uint32_t PushNextNodeId(DxcHLSLReflection &Refl, const SourceManager &SM, + const LangOptions &LangOpts, + const std::string &UnqualifiedName, Decl *Decl, + DxcHLSLNodeType Type, uint32_t ParentNodeId, + uint32_t LocalId, const SourceRange *Range = nullptr) { + + assert(Refl.Nodes.size() < (uint32_t)(1 << 24) && "Nodes overflow"); + assert(LocalId < (uint32_t)(1 << 24) && "LocalId overflow"); + + uint32_t nodeId = Refl.Nodes.size(); + + uint32_t annotationStart = (uint32_t) Refl.Annotations.size(); + uint16_t annotationCount = 0; + + if (Decl) { + for (const Attr *attr : Decl->attrs()) { + if (const AnnotateAttr *annotate = dyn_cast(attr)) { + + assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); + + Refl.Annotations.push_back(DxcHLSLAnnotation( + RegisterString(Refl, annotate->getAnnotation().str(), true), + false)); + + assert(annotationCount != uint16_t(-1) && + "Annotation count out of bounds"); + ++annotationCount; + + } else if (const HLSLShaderAttr *shaderAttr = + dyn_cast(attr)) { + + assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); + + Refl.Annotations.push_back(DxcHLSLAnnotation( + RegisterString( + Refl, "shader(\"" + shaderAttr->getStage().str() + "\")", true), + true)); + + assert(annotationCount != uint16_t(-1) && + "Annotation count out of bounds"); + ++annotationCount; + } + } + } + + if (Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { + + uint16_t sourceLineCount = 0; + uint32_t sourceLineStart = 0; + uint32_t sourceColumnStart = 0; + uint32_t sourceColumnEnd = 0; + + uint16_t fileNameId = (uint16_t)-1; + + SourceRange range = + Decl ? Decl->getSourceRange() : (Range ? *Range : SourceRange()); + + SourceLocation start = range.getBegin(); + SourceLocation end = range.getEnd(); + + if (start.isValid() && end.isValid()) { + + PresumedLoc presumed = SM.getPresumedLoc(start); + + SourceLocation realEnd = SM.getFileLoc(end); + SourceLocation endOfToken = + Lexer::getLocForEndOfToken(realEnd, 0, SM, LangOpts); + PresumedLoc presumedEnd = SM.getPresumedLoc(endOfToken); + + if (presumed.isValid() && presumedEnd.isValid()) { + + uint32_t startLine = presumed.getLine(); + uint32_t startCol = presumed.getColumn(); + uint32_t endLine = presumedEnd.getLine(); + uint32_t endCol = presumedEnd.getColumn(); + + std::string fileName = presumed.getFilename(); + + assert(fileName == presumedEnd.getFilename() && + "End and start are not in the same file"); + + auto it = Refl.StringToSourceId.find(fileName); + uint32_t i; + + if (it == Refl.StringToSourceId.end()) { + i = (uint32_t)Refl.Sources.size(); + Refl.Sources.push_back(RegisterString(Refl, fileName, false)); + Refl.StringToSourceId[fileName] = i; + } + + else { + i = it->second; + } + + assert(i < 65535 && "Source file count is limited to 16-bit"); + assert((endLine - startLine) < 65535 && + "Source line count is limited to 16-bit"); + assert(startLine < 1048576 && "Source line start is limited to 20-bit"); + assert(startCol < 131072 && "Column start is limited to 17-bit"); + assert(endCol < 131072 && "Column end is limited to 17-bit"); + + sourceLineCount = uint16_t(endLine - startLine + 1); + sourceLineStart = startLine; + sourceColumnStart = startCol; + sourceColumnEnd = endCol; + fileNameId = (uint16_t)i; + } + } + + uint32_t nameId = RegisterString(Refl, UnqualifiedName, false); + + Refl.NodeSymbols.push_back( + DxcHLSLNodeSymbol(nameId, fileNameId, sourceLineCount, sourceLineStart, + sourceColumnStart, sourceColumnEnd)); + } + + Refl.Nodes.push_back(DxcHLSLNode{Type, LocalId, annotationStart, 0, + ParentNodeId, annotationCount}); + + uint32_t parentParent = ParentNodeId; + + while (parentParent != 0) { + DxcHLSLNode &parent = Refl.Nodes[parentParent]; + parent.IncreaseChildCount(); + parentParent = parent.GetParentId(); + } + + Refl.Nodes[0].IncreaseChildCount(); + + return nodeId; +} + +static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, + std::string TypeName, + bool IsWrite, + const CXXRecordDecl *RecordDecl) { + + DxcRegisterTypeInfo type = {}; + type.RegisterType = IsWrite ? D3D_SIT_UAV_RWTYPED : D3D_SIT_TEXTURE; + type.SampleCount = (uint32_t)-1; + + //Parse return type and dimensions + + const ClassTemplateSpecializationDecl *textureTemplate = + dyn_cast(RecordDecl); + + assert(textureTemplate && "Expected texture template"); + + const ArrayRef& textureParams = textureTemplate->getTemplateArgs().asArray(); + + assert(textureParams.size() == 1 && + textureParams[0].getKind() == TemplateArgument::Type && + "Expected template args"); + + QualType valueType = textureParams[0].getAsType(); + QualType desugared = valueType.getDesugaredType(ASTCtx); + + uint32_t dimensions; + + if (const BuiltinType *bt = dyn_cast(desugared)) + dimensions = 1; + + else { + + const RecordType *RT = desugared->getAs(); + assert(RT && "Expected record type"); + + const CXXRecordDecl *RD = dyn_cast(RT->getDecl()); + assert(RT && "Expected record decl"); + + const ClassTemplateSpecializationDecl *vectorType = + dyn_cast(RD); + + assert(vectorType && + "Expected vector type as template inside of texture template"); + + const ArrayRef &vectorParams = + vectorType->getTemplateArgs().asArray(); + + assert(vectorParams.size() == 2 && + vectorParams[0].getKind() == TemplateArgument::Type && + vectorParams[1].getKind() == TemplateArgument::Integral && + "Expected vector to be vector"); + + valueType = vectorParams[0].getAsType(); + desugared = valueType.getDesugaredType(ASTCtx); + + dimensions = vectorParams[1].getAsIntegral().getZExtValue(); + } + + if (desugared->isFloatingType()) { + type.TextureValue = desugared->isSpecificBuiltinType(BuiltinType::Double) + ? D3D_RETURN_TYPE_DOUBLE + : D3D_RETURN_TYPE_FLOAT; + } else if (desugared->isIntegerType()) { + const auto &semantics = ASTCtx.getTypeInfo(desugared); + if (semantics.Width == 64) { + type.TextureValue = D3D_RETURN_TYPE_MIXED; + } else { + type.TextureValue = desugared->isUnsignedIntegerType() + ? D3D_RETURN_TYPE_UINT + : D3D_RETURN_TYPE_SINT; + } + } + + else { + type.TextureValue = D3D_RETURN_TYPE_MIXED; + } + + switch (dimensions) { + case 2: + type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENT_0; + break; + case 3: + type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENT_1; + break; + case 4: + type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENTS; + break; + } + + //Parse type + + if (TypeName == "Buffer") { + type.TextureDimension = D3D_SRV_DIMENSION_BUFFER; + return type; + } + + bool isFeedback = false; + + if (TypeName.size() > 8 && TypeName.substr(0, 8) == "Feedback") { + isFeedback = true; + TypeName = TypeName.substr(8); + type.RegisterType = D3D_SIT_UAV_FEEDBACKTEXTURE; + } + + bool isArray = false; + + if (TypeName.size() > 5 && TypeName.substr(TypeName.size() - 5) == "Array") { + isArray = true; + TypeName = TypeName.substr(0, TypeName.size() - 5); + } + + if (TypeName == "Texture2D") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2D; + + else if (TypeName == "TextureCube") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURECUBE; + + else if (TypeName == "Texture3D") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE3D; + + else if (TypeName == "Texture1D") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE1D; + + else if (TypeName == "Texture2DMS") { + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2DMS; + type.SampleCount = 0; + } + + if (isArray) //Arrays are always 1 behind the regular type + type.TextureDimension = (D3D_SRV_DIMENSION)(type.TextureDimension + 1); + + return type; +} + +static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, + QualType Type) { + + QualType realType = Type.getDesugaredType(ASTCtx); + const RecordType *RT = realType->getAs(); + assert(RT && "GetRegisterTypeInfo() type is not a RecordType"); + + const CXXRecordDecl *recordDecl = RT->getAsCXXRecordDecl(); + assert(recordDecl && "GetRegisterTypeInfo() type is not a CXXRecordDecl"); + + std::string typeName = recordDecl->getNameAsString(); + + if (typeName.size() >= 17 && + typeName.substr(0, 17) == "RasterizerOrdered") { + typeName = typeName.substr(17); + } + + if (typeName == "SamplerState" || typeName == "SamplerComparisonState") { + return {D3D_SIT_SAMPLER, typeName == "SamplerComparisonState" + ? D3D_SIF_COMPARISON_SAMPLER + : (D3D_SHADER_INPUT_FLAGS)0}; + } + + DxcRegisterTypeInfo info = {}; + + if (const ClassTemplateSpecializationDecl *spec = + dyn_cast(recordDecl)) { + + const ArrayRef &array = + spec->getTemplateArgs().asArray(); + + if (array.size() == 1) + info.SampleCount = (uint32_t) (ASTCtx.getTypeSize(array[0].getAsType()) / 8); + } + + if (typeName == "AppendStructuredBuffer") { + info.RegisterType = D3D_SIT_UAV_APPEND_STRUCTURED; + return info; + } + + if (typeName == "ConsumeStructuredBuffer") { + info.RegisterType = D3D_SIT_UAV_CONSUME_STRUCTURED; + return info; + } + + if (typeName == "RaytracingAccelerationStructure") { + info.RegisterType = D3D_SIT_RTACCELERATIONSTRUCTURE; + info.SampleCount = (uint32_t)-1; + return info; + } + + if (typeName == "TextureBuffer") { + info.RegisterType = D3D_SIT_TBUFFER; + return info; + } + + if (typeName == "ConstantBuffer") { + info.RegisterType = D3D_SIT_CBUFFER; + return info; + } + + bool isWrite = + typeName.size() > 2 && typeName[0] == 'R' && typeName[1] == 'W'; + + if (isWrite) + typeName = typeName.substr(2); + + if (typeName == "StructuredBuffer") { + info.RegisterType = + isWrite ? D3D_SIT_UAV_RWSTRUCTURED : D3D_SIT_STRUCTURED; + return info; + } + + if (typeName == "ByteAddressBuffer") { + info.RegisterType = + isWrite ? D3D_SIT_UAV_RWBYTEADDRESS : D3D_SIT_BYTEADDRESS; + return info; + } + + return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); +} + +static uint32_t PushArray(DxcHLSLReflection &Refl, uint32_t ArraySizeFlat, + const std::vector &ArraySize) { + + if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) + return (uint32_t)-1; + + assert(Refl.Arrays.size() < (uint32_t)((1u << 31) - 1) && "Arrays would overflow"); + uint32_t arrayId = (uint32_t)Refl.Arrays.size(); + + uint32_t arrayCountStart = (uint32_t)Refl.ArraySizes.size(); + uint32_t numArrayElements = std::min((size_t)8, ArraySize.size()); + assert(Refl.ArraySizes.size() + numArrayElements < ((1 << 28) - 1) && + "Array elements would overflow"); + + for (uint32_t i = 0; i < ArraySize.size() && i < 8; ++i) { + + uint32_t arraySize = ArraySize[i]; + + // Flatten rest of array to at least keep consistent array elements + if (i == 7) + for (uint32_t j = i + 1; j < ArraySize.size(); ++j) + arraySize *= ArraySize[j]; + + Refl.ArraySizes.push_back(arraySize); + } + + DxcHLSLArray arr = {numArrayElements, arrayCountStart}; + + for (uint32_t i = 0; i < Refl.Arrays.size(); ++i) + if (Refl.Arrays[i] == arr) + return i; + + Refl.Arrays.push_back(arr); + return arrayId; +} + +uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflection &Refl, + QualType Original, bool DefaultRowMaj) { + + // Unwrap array + + uint32_t arraySize = 1; + QualType underlying = Original, forName = Original; + std::vector arrayElem; + + while (const ConstantArrayType *arr = + dyn_cast(underlying)) { + uint32_t current = arr->getSize().getZExtValue(); + arrayElem.push_back(current); + arraySize *= arr->getSize().getZExtValue(); + forName = arr->getElementType(); + underlying = forName.getCanonicalType(); + } + + underlying = underlying.getCanonicalType(); + + // Name; Omit struct, class and const keywords + + PrintingPolicy policy(ASTCtx.getLangOpts()); + policy.SuppressScope = false; + policy.AnonymousTagLocations = false; + policy.SuppressTagKeyword = true; + + bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + uint32_t nameId = + hasSymbols + ? RegisterString( + Refl, forName.getLocalUnqualifiedType().getAsString(policy), + false) + : uint32_t(-1); + + uint32_t arrayId = PushArray(Refl, arraySize, arrayElem); + uint32_t elementsOrArrayId = 0; + + if (arrayId != (uint32_t)-1) + elementsOrArrayId = (1u << 31) | arrayId; + + else + elementsOrArrayId = arraySize > 1 ? arraySize : 0; + + //Unwrap vector and matrix + //And base type + + D3D_SHADER_VARIABLE_CLASS cls = D3D_SVC_STRUCT; + uint8_t rows = 0, columns = 0; + + uint32_t membersCount = 0; + uint32_t membersOffset = 0; + + uint32_t baseType = uint32_t(-1); + + if (const RecordType *record = underlying->getAs()) { + + bool standardType = false; + + RecordDecl *recordDecl = record->getDecl(); + + if (const ClassTemplateSpecializationDecl *templateClass = + dyn_cast(recordDecl)) { + + const std::string &name = templateClass->getIdentifier()->getName(); + + const ArrayRef ¶ms = + templateClass->getTemplateArgs().asArray(); + + uint32_t magic = 0; + std::memcpy(&magic, name.c_str(), std::min(sizeof(magic), name.size())); + + std::string_view subs = + name.size() < sizeof(magic) + ? std::string_view() + : std::string_view(name).substr(sizeof(magic)); + + switch (magic) { + + case DXC_FOURCC('v', 'e', 'c', 't'): + + if (subs == "or") { + + rows = 1; + + assert(params.size() == 2 && + params[0].getKind() == TemplateArgument::Type && + params[1].getKind() == TemplateArgument::Integral && + "Expected vector to be vector"); + + underlying = params[0].getAsType(); + columns = params[1].getAsIntegral().getSExtValue(); + cls = D3D_SVC_VECTOR; + standardType = true; + } + + break; + + case DXC_FOURCC('m', 'a', 't', 'r'): + + if (subs == "ix") { + + assert(params.size() == 3 && + params[0].getKind() == TemplateArgument::Type && + params[1].getKind() == TemplateArgument::Integral && + params[2].getKind() == TemplateArgument::Integral && + "Expected matrix to be matrix"); + + underlying = params[0].getAsType(); + columns = params[1].getAsIntegral().getSExtValue(); + rows = params[2].getAsIntegral().getSExtValue(); + + bool isRowMajor = DefaultRowMaj; + + HasHLSLMatOrientation(Original, &isRowMajor); + + if (!isRowMajor) + std::swap(rows, columns); + + cls = isRowMajor ? D3D_SVC_MATRIX_ROWS : D3D_SVC_MATRIX_COLUMNS; + standardType = true; + } + + break; + } + + // TODO: + // D3D_SVT_TEXTURE = 5, + // D3D_SVT_TEXTURE1D = 6, + // D3D_SVT_TEXTURE2D = 7, + // D3D_SVT_TEXTURE3D = 8, + // D3D_SVT_TEXTURECUBE = 9, + // D3D_SVT_SAMPLER = 10, + // D3D_SVT_SAMPLER1D = 11, + // D3D_SVT_SAMPLER2D = 12, + // D3D_SVT_SAMPLER3D = 13, + // D3D_SVT_SAMPLERCUBE = 14, + // D3D_SVT_BUFFER = 25, + // D3D_SVT_CBUFFER = 26, + // D3D_SVT_TBUFFER = 27, + // D3D_SVT_TEXTURE1DARRAY = 28, + // D3D_SVT_TEXTURE2DARRAY = 29, + // D3D_SVT_TEXTURE2DMS = 32, + // D3D_SVT_TEXTURE2DMSARRAY = 33, + // D3D_SVT_TEXTURECUBEARRAY = 34, + // D3D_SVT_RWTEXTURE1D = 40, + // D3D_SVT_RWTEXTURE1DARRAY = 41, + // D3D_SVT_RWTEXTURE2D = 42, + // D3D_SVT_RWTEXTURE2DARRAY = 43, + // D3D_SVT_RWTEXTURE3D = 44, + // D3D_SVT_RWBUFFER = 45, + // D3D_SVT_BYTEADDRESS_BUFFER = 46, + // D3D_SVT_RWBYTEADDRESS_BUFFER = 47, + // D3D_SVT_STRUCTURED_BUFFER = 48, + // D3D_SVT_RWSTRUCTURED_BUFFER = 49, + // D3D_SVT_APPEND_STRUCTURED_BUFFER = 50, + // D3D_SVT_CONSUME_STRUCTURED_BUFFER = 51, + } + + // Fill members + + if (!standardType && recordDecl->isCompleteDefinition()) { + + //Base types + + if (CXXRecordDecl *cxxRecordDecl = dyn_cast(recordDecl)) + if (cxxRecordDecl->getNumBases()) { + for (auto &I : cxxRecordDecl->bases()) { + + QualType qualType = I.getType(); + CXXRecordDecl *BaseDecl = + cast(qualType->castAs()->getDecl()); + + // TODO: Interfaces? + if (BaseDecl->isInterface()) + continue; + + assert(baseType == uint32_t(-1) && + "Multiple base types isn't supported in HLSL"); + + baseType = GenerateTypeInfo(ASTCtx, Refl, qualType, DefaultRowMaj); + } + } + + //Inner types + + for (Decl *decl : recordDecl->decls()) { + + // TODO: We could query other types VarDecl + + FieldDecl *fieldDecl = dyn_cast(decl); + + if (!fieldDecl) + continue; + + QualType original = fieldDecl->getType(); + std::string name = fieldDecl->getName(); + + uint32_t nameId = hasSymbols ? RegisterString(Refl, name, false) : uint32_t(-1); + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); + + if (!membersCount) + membersOffset = (uint32_t) Refl.MemberTypeIds.size(); + + assert(Refl.MemberTypeIds.size() <= (uint32_t)-1 && + "Members out of bounds"); + + Refl.MemberTypeIds.push_back(typeId); + + if (hasSymbols) + Refl.MemberNameIds.push_back(nameId); + + ++membersCount; + } + } + } + + //Type name + + D3D_SHADER_VARIABLE_TYPE type = D3D_SVT_VOID; + + if (const BuiltinType *bt = dyn_cast(underlying)) { + + if (!rows) + rows = columns = 1; + + if (cls == D3D_SVC_STRUCT) + cls = D3D_SVC_SCALAR; + + switch (bt->getKind()) { + + case BuiltinType::Void: + type = D3D_SVT_VOID; + break; + + case BuiltinType::Min10Float: + type = D3D_SVT_MIN10FLOAT; + break; + + case BuiltinType::Min16Float: + type = D3D_SVT_MIN16FLOAT; + break; + + case BuiltinType::HalfFloat: + case BuiltinType::Half: + type = D3D_SVT_FLOAT16; + break; + + case BuiltinType::Short: + type = D3D_SVT_INT16; + break; + + case BuiltinType::Min12Int: + type = D3D_SVT_MIN12INT; + break; + + case BuiltinType::Min16Int: + type = D3D_SVT_MIN16INT; + break; + + case BuiltinType::Min16UInt: + type = D3D_SVT_MIN16UINT; + break; + + case BuiltinType::UShort: + type = D3D_SVT_UINT16; + break; + + case BuiltinType::Float: + type = D3D_SVT_FLOAT; + break; + + case BuiltinType::Int: + type = D3D_SVT_INT; + break; + + case BuiltinType::UInt: + type = D3D_SVT_UINT; + break; + + case BuiltinType::Bool: + type = D3D_SVT_BOOL; + break; + + case BuiltinType::Double: + type = D3D_SVT_DOUBLE; + break; + + case BuiltinType::ULongLong: + type = D3D_SVT_UINT64; + break; + + case BuiltinType::LongLong: + type = D3D_SVT_INT64; + break; + + default: + assert(false && "Invalid builtin type"); + break; + } + } + + //Insert + + assert(Refl.Types.size() < (uint32_t)-1 && "Type id out of bounds"); + + DxcHLSLType hlslType(baseType, elementsOrArrayId, cls, type, rows, + columns, membersCount, membersOffset); + + uint32_t i = 0, j = (uint32_t)Refl.Types.size(); + + for (; i < j; ++i) + if (Refl.Types[i] == hlslType) + break; + + if (i == j) { + + if (hasSymbols) + Refl.TypeNameIds.push_back(nameId); + + Refl.Types.push_back(hlslType); + } + + return i; +} + +static D3D_CBUFFER_TYPE GetBufferType(uint8_t Type) { + + switch (Type) { + + case D3D_SIT_CBUFFER: + return D3D_CT_CBUFFER; + + case D3D_SIT_TBUFFER: + return D3D_CT_TBUFFER; + + case D3D_SIT_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: + return D3D_CT_RESOURCE_BIND_INFO; + + default: + return D3D_CT_INTERFACE_POINTERS; + } +} + +static void FillReflectionRegisterAt( + const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, + DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, + ValueDecl *ValDesc, const std::vector &ArraySize, + DxcHLSLReflection &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId, + bool DefaultRowMaj) { + + ArrayRef UA = ValDesc->getUnusualAnnotations(); + + hlsl::RegisterAssignment *reg = nullptr; + + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { + + if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) + continue; + + reg = cast(*It); + } + + assert(reg && "Found a register missing a RegisterAssignment, even though " + "GenerateConsistentBindings should have already generated it"); + + DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, + DxcHLSLNodeType::Register, ParentNodeId, (uint32_t)Refl.Registers.size()); + + uint32_t arrayId = PushArray(Refl, ArraySizeFlat, ArraySize); + + uint32_t bufferId = 0; + D3D_CBUFFER_TYPE bufferType = GetBufferType(inputType.RegisterType); + + if(bufferType != D3D_CT_INTERFACE_POINTERS) { + bufferId = (uint32_t) Refl.Buffers.size(); + Refl.Buffers.push_back({bufferType, nodeId}); + } + + DxcHLSLRegister regD3D12 = { + + inputType.RegisterType, + reg->RegisterNumber, + ArraySizeFlat, + (uint32_t)inputType.RegisterFlags, + inputType.TextureValue, + inputType.TextureDimension, + inputType.SampleCount, + reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() + : AutoBindingSpace, + nodeId, + arrayId, + bufferId + }; + + Refl.Registers.push_back(regD3D12); + + bool isListType = true; + + switch (inputType.RegisterType) { + + case D3D_SIT_CBUFFER: + case D3D_SIT_TBUFFER: + isListType = false; + [[fallthrough]]; + + case D3D_SIT_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: { + + const RecordType *recordType = Type->getAs(); + + assert(recordType && "Invalid type (not RecordType)"); + + const ClassTemplateSpecializationDecl *templateDesc = + dyn_cast(recordType->getDecl()); + + assert(templateDesc && "Invalid template type"); + + const ArrayRef ¶ms = + templateDesc->getTemplateArgs().asArray(); + + assert(params.size() == 1 && + params[0].getKind() == TemplateArgument::Type && "Expected Type"); + + QualType innerType = params[0].getAsType(); + + // The name of the inner struct is $Element if 'array', otherwise equal to + // register name + + uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, innerType, DefaultRowMaj); + + SourceRange sourceRange = ValDesc->getSourceRange(); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), + isListType ? "$Element" : ValDesc->getName(), nullptr, + DxcHLSLNodeType::Variable, nodeId, typeId, &sourceRange); + + break; + } + } +} + +//TODO: Debug code +class PrintfStream : public llvm::raw_ostream { +public: + PrintfStream() { SetUnbuffered(); } + +private: + void write_impl(const char *Ptr, size_t Size) override { + printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly + } + + uint64_t current_pos() const override { return 0; } +}; + +template +void RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, + DxcHLSLReflection &Refl, const T &Decls, + bool DefaultRowMaj, uint32_t ParentId) { + + for (Decl *decl : Decls) { + + ValueDecl *valDecl = dyn_cast(decl); + assert(valDecl && "Decl was expected to be a ValueDecl but wasn't"); + QualType original = valDecl->getType(); + + const std::string &name = valDecl->getName(); + + uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); + + uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, decl, + DxcHLSLNodeType::Variable, ParentId, typeId); + + //Handle struct recursion + + if (RecordDecl *recordDecl = dyn_cast(decl)) { + + if (!recordDecl->isCompleteDefinition()) + continue; + + RecurseBuffer(ASTCtx, SM, Refl, recordDecl->fields(), DefaultRowMaj, nodeId); + } + } +} + +uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcHLSLReflection &Refl, + const SourceManager &SM, DeclContext *Buffer, + uint32_t NodeId, D3D_CBUFFER_TYPE Type, + bool DefaultRowMaj) { + + assert(Refl.Buffers.size() < (uint32_t)-1 && "Buffer id out of bounds"); + uint32_t bufferId = (uint32_t)Refl.Buffers.size(); + + RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), DefaultRowMaj, NodeId); + + Refl.Buffers.push_back({Type, NodeId}); + + return bufferId; +} + +/* +static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, + DxcHLSLReflection &Refl, const SourceManager &SM, + uint32_t ParentNodeId) { + + PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); + + QualType desugared = Type.getDesugaredType(ASTCtx); + + PrintfStream str; + desugared.print(str, printingPolicy); + + if (Decl) + Decl->print(str); + + //Generate parameter + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), + Decl && dyn_cast(Decl) ? dyn_cast(Decl)->getName() + : "", + Decl, DxcHLSLNodeType::Parameter, ParentNodeId, + (uint32_t)Refl.Parameters.size()); + + std::string semanticName; + + if (NamedDecl *ValDesc = dyn_cast(Decl)) { + + ArrayRef UA = ValDesc->getUnusualAnnotations(); + + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { + + if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_SemanticDecl) + continue; + + semanticName = cast(*It)->SemanticName; + } + } + + DxcHLSLParameter parameter{std::move(semanticName)}; + + type, clss, rows, columns, interpolationMode, flags; + parameter.NodeId = nodeId; + + Refl.Parameters.push_back(parameter); + + //It's a struct, add parameters recursively +}*/ + +static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, + DiagnosticsEngine &Diags, + const SourceManager &SM, + DxcHLSLReflection &Refl, + uint32_t AutoBindingSpace, + uint32_t Depth, + D3D12_HLSL_REFLECTION_FEATURE Features, + uint32_t ParentNodeId, bool DefaultRowMaj) { + + PrintfStream pfStream; + + PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); + + printingPolicy.SuppressInitializers = true; + printingPolicy.AnonymousTagLocations = false; + printingPolicy.TerseOutput = + true; // No inheritance list, trailing semicolons, etc. + printingPolicy.PolishForDeclaration = true; // Makes it print as a decl + printingPolicy.SuppressSpecifiers = false; // Prints e.g. "static" or "inline" + printingPolicy.SuppressScope = true; + + // Traverse AST to grab reflection data + + //TODO: Niels, scopes (if/switch/for/empty scope) + + for (Decl *it : Ctx.decls()) { + + SourceLocation Loc = it->getLocation(); + if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) + continue; + + if (HLSLBufferDecl *CBuffer = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) + continue; + + // TODO: Add for reflection even though it might not be important + + if (Depth != 0) + continue; + + hlsl::RegisterAssignment *reg = nullptr; + ArrayRef UA = CBuffer->getUnusualAnnotations(); + + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { + + if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) + continue; + + reg = cast(*It); + } + + assert(reg && + "Found a cbuffer missing a RegisterAssignment, even though " + "GenerateConsistentBindings should have already generated it"); + + uint32_t nodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), CBuffer->getName(), + CBuffer, DxcHLSLNodeType::Register, ParentNodeId, + (uint32_t)Refl.Registers.size()); + + uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, SM, CBuffer, nodeId, + D3D_CT_CBUFFER, DefaultRowMaj); + + DxcHLSLRegister regD3D12 = { + + D3D_SIT_CBUFFER, + reg->RegisterNumber, + 1, + (uint32_t) D3D_SIF_USERPACKED, + (D3D_RESOURCE_RETURN_TYPE) 0, + D3D_SRV_DIMENSION_UNKNOWN, + 0, + reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() + : AutoBindingSpace, + nodeId, + (uint32_t)-1, + bufferId + }; + + Refl.Registers.push_back(regD3D12); + } + + else if (FunctionDecl *Func = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS)) + continue; + + const FunctionDecl *Definition = nullptr; + + uint32_t nodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), Func->getName(), Func, + DxcHLSLNodeType::Function, ParentNodeId, + (uint32_t)Refl.Functions.size()); + + bool hasDefinition = Func->hasBody(Definition); + DxcHLSLFunction func = {nodeId, Func->getNumParams(), + !Func->getReturnType().getTypePtr()->isVoidType(), + hasDefinition}; + + /* + for (uint32_t i = 0; i < func.NumParameters; ++i) + AddFunctionParameters(ASTCtx, Func->getParamDecl(i)->getType(), + Func->getParamDecl(i), Refl, SM, nodeId); + + if (func.HasReturn) + AddFunctionParameters(ASTCtx, Func->getReturnType(), nullptr, Refl, SM, + nodeId);*/ + + Refl.Functions.push_back(std::move(func)); + + if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { + RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, + nodeId, DefaultRowMaj); + } + } + + else if (TypedefDecl *Typedef = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + // Typedef->print(pfStream, printingPolicy); + } + + else if (TypeAliasDecl *TypeAlias = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + // TypeAlias->print(pfStream, printingPolicy); + } + + else if (EnumDecl *Enum = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), Enum->getName(), Enum, + DxcHLSLNodeType::Enum, ParentNodeId, (uint32_t)Refl.Enums.size()); + + for (EnumConstantDecl *EnumValue : Enum->enumerators()) { + + uint32_t childNodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), EnumValue->getName(), + EnumValue, DxcHLSLNodeType::EnumValue, nodeId, + (uint32_t)Refl.EnumValues.size()); + + Refl.EnumValues.push_back( + {EnumValue->getInitVal().getSExtValue(), childNodeId}); + } + + assert(Refl.EnumValues.size() < (uint32_t)(1 << 30) && + "Enum values overflow"); + + QualType enumType = Enum->getIntegerType(); + QualType desugared = enumType.getDesugaredType(ASTCtx); + const auto &semantics = ASTCtx.getTypeInfo(desugared); + + D3D12_HLSL_ENUM_TYPE type; + + switch (semantics.Width) { + + default: + case 32: + type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT + : D3D12_HLSL_ENUM_TYPE_INT; + break; + + case 16: + type = desugared->isUnsignedIntegerType() + ? D3D12_HLSL_ENUM_TYPE_UINT16_T + : D3D12_HLSL_ENUM_TYPE_INT16_T; + break; + + case 64: + type = desugared->isUnsignedIntegerType() + ? D3D12_HLSL_ENUM_TYPE_UINT64_T + : D3D12_HLSL_ENUM_TYPE_INT64_T; + break; + } + + Refl.Enums.push_back({nodeId, type}); + } + + else if (ValueDecl *ValDecl = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) + continue; + + //TODO: Handle values + + //ValDecl->print(pfStream); + + uint32_t arraySize = 1; + QualType type = ValDecl->getType(); + std::vector arrayElem; + + while (const ConstantArrayType *arr = + dyn_cast(type)) { + uint32_t current = arr->getSize().getZExtValue(); + arrayElem.push_back(current); + arraySize *= arr->getSize().getZExtValue(); + type = arr->getElementType(); + } + + if (!IsHLSLResourceType(type)) + continue; + + // TODO: Add for reflection even though it might not be important + + if (Depth != 0) + continue; + + FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, ValDecl, + arrayElem, Refl, AutoBindingSpace, ParentNodeId, + DefaultRowMaj); + } + + else if (RecordDecl *RecDecl = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + //RecDecl->print(pfStream, printingPolicy); + /*RecursiveReflectHLSL(*RecDecl, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, InclusionFlags, nodeId);*/ + } + + else if (NamespaceDecl *Namespace = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES)) + continue; + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), Namespace->getName(), Namespace, + DxcHLSLNodeType::Namespace, ParentNodeId, 0); + + RecursiveReflectHLSL(*Namespace, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, nodeId, + DefaultRowMaj); + } + } +} + +DxcHLSLReflection::DxcHLSLReflection(clang::CompilerInstance &Compiler, + clang::TranslationUnitDecl &Ctx, + uint32_t AutoBindingSpace, + D3D12_HLSL_REFLECTION_FEATURE Features, + bool DefaultRowMaj) { + + DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); + const SourceManager &SM = Compiler.getSourceManager(); + + *this = {}; + this->Features = Features; + + if (Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { + Strings.push_back(""); + StringsToId[""] = 0; + NodeSymbols.push_back(DxcHLSLNodeSymbol(0, 0, 0, 0, 0, 0)); + } + + Nodes.push_back( + DxcHLSLNode{DxcHLSLNodeType::Namespace, 0, 0, 0, 0xFFFF, 0}); + + RecursiveReflectHLSL(Ctx, Compiler.getASTContext(), Diags, SM, *this, + AutoBindingSpace, 0, Features, 0, DefaultRowMaj); +} + +//TODO: Debug print code + +static char RegisterGetSpaceChar(const DxcHLSLRegister ®) { + + switch (reg.Type) { + + case D3D_SIT_UAV_RWTYPED: + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_RWBYTEADDRESS: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: + case D3D_SIT_UAV_FEEDBACKTEXTURE: + return 'u'; + + case D3D_SIT_CBUFFER: + return 'b'; + + case D3D_SIT_SAMPLER: + return 's'; + + default: + return 't'; + } +} + +static std::string RegisterGetArraySize(const DxcHLSLReflection &Refl, const DxcHLSLRegister ®) { + + if (reg.ArrayId != (uint32_t)-1) { + + DxcHLSLArray arr = Refl.Arrays[reg.ArrayId]; + std::string str; + + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) + str += "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart() + i]) + "]"; + + return str; + } + + return reg.BindCount > 1 ? "[" + std::to_string(reg.BindCount) + "]" : ""; +} + +static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { + + static const char *arr[] = { + "uint", "int", "uint64_t", "int64_t", "uint16_t", "int16_t", + }; + + return arr[type]; +} + +static std::string NodeTypeToString(DxcHLSLNodeType type) { + + static const char *arr[] = {"Register", "Function", "Enum", "EnumValue", + "Namespace", "Typedef", "Using", "Variable"}; + + return arr[(int)type]; +} + +static std::string GetBuiltinTypeName(const DxcHLSLReflection &Refl, + const DxcHLSLType &Type) { + + std::string type; + + if (Type.Class != D3D_SVC_STRUCT) { + + static const char *arr[] = {"void", + "bool", + "int", + "float", + "string", + NULL, + "Texture1D", + "Texture2D", + "Texture3D", + "TextureCube", + "SamplerState", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "uint", + "uint8_t", + NULL, + NULL, + NULL, + NULL, + "Buffer", + "ConstantBuffer", + NULL, + "Texture1DArray", + "Texture2DArray", + NULL, + NULL, + "Texture2DMS", + "Texture2DMSArray", + "TextureCubeArray", + NULL, + NULL, + NULL, + NULL, + "double", + "RWTexture1D", + "RWTexture1DArray", + "RWTexture2D", + "RWTexture2DArray", + "RWTexture3D", + "RWBuffer", + "ByteAddressBuffer", + "RWByteAddressBuffer", + "StructuredBuffer", + "RWStructuredBuffer", + "AppendStructuredBuffer", + "ConsumeStructuredBuffer", + "min8float", + "min10float", + "min16float", + "min12int", + "min16int", + "min16uint", + "int16_t", + "uint16_t", + "float16_t", + "int64_t", + "uint64_t"}; + + const char *ptr = arr[Type.Type]; + + if (ptr) + type = ptr; + } + + switch (Type.Class) { + + case D3D_SVC_MATRIX_ROWS: + case D3D_SVC_VECTOR: + + type += std::to_string(Type.Columns); + + if (Type.Class == D3D_SVC_MATRIX_ROWS) + type += "x" + std::to_string(Type.Rows); + + break; + + case D3D_SVC_MATRIX_COLUMNS: + type += std::to_string(Type.Rows) + "x" + std::to_string(Type.Columns); + break; + } + + return type; +} + +static std::string PrintTypeInfo(const DxcHLSLReflection &Refl, + const DxcHLSLType &Type, + const std::string &PreviousTypeName) { + + std::string result; + + if (Type.IsMultiDimensionalArray()) { + + const DxcHLSLArray &arr = Refl.Arrays[Type.GetMultiDimensionalArrayId()]; + + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) + result += + "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart() + i]) + "]"; + + } + + else if (Type.IsArray()) + result += "[" + std::to_string(Type.Get1DElements()) + "]"; + + // Obtain type name (returns empty if it's not a builtin type) + + std::string underlyingTypeName = GetBuiltinTypeName(Refl, Type); + + if (PreviousTypeName != underlyingTypeName && underlyingTypeName.size()) + result += " (" + underlyingTypeName + ")"; + + return result; +} + +static void RecursePrintType(const DxcHLSLReflection &Refl, uint32_t TypeId, + uint32_t Depth, const char *Prefix = "") { + + const DxcHLSLType &type = Refl.Types[TypeId]; + + bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + std::string name = hasSymbols ? Refl.Strings[Refl.TypeNameIds[TypeId]] + : GetBuiltinTypeName(Refl, type); + + if (name.empty() && !hasSymbols) + name = "(unknown)"; + + printf("%s%s%s%s\n", std::string(Depth, '\t').c_str(), Prefix, name.c_str(), + PrintTypeInfo(Refl, type, name).c_str()); + + if (type.BaseClass != uint32_t(-1)) + RecursePrintType(Refl, type.BaseClass, Depth + 1, Prefix); + + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { + + uint32_t memberId = type.GetMemberStart() + i; + std::string prefix = + (hasSymbols ? Refl.Strings[Refl.MemberNameIds[memberId]] : "(unknown)") + ": "; + + RecursePrintType(Refl, Refl.MemberTypeIds[memberId], Depth + 1, prefix.c_str()); + } +} + +uint32_t RecursePrint(const DxcHLSLReflection &Refl, uint32_t NodeId, + uint32_t Depth, uint32_t IndexInParent) { + + const DxcHLSLNode &node = Refl.Nodes[NodeId]; + + uint32_t typeToPrint = (uint32_t)-1; + + if (NodeId) { + + bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + printf("%s%s %s\n", std::string(Depth - 1, '\t').c_str(), + NodeTypeToString(node.GetNodeType()).c_str(), + hasSymbols ? Refl.Strings[Refl.NodeSymbols[NodeId].NameId].c_str() + : "(unknown)"); + + for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) { + + const DxcHLSLAnnotation &annotation = + Refl.Annotations[node.GetAnnotationStart() + i]; + + printf(annotation.GetIsBuiltin() ? "%s[%s]\n" : "%s[[%s]]\n", + std::string(Depth, '\t').c_str(), + Refl.StringsNonDebug[annotation.GetStringNonDebug()] + .c_str()); + } + + uint32_t localId = node.GetLocalId(); + + switch (node.GetNodeType()) { + + case DxcHLSLNodeType::Register: { + const DxcHLSLRegister ® = Refl.Registers[localId]; + printf("%s%s : register(%c%u, space%u);\n", + std::string(Depth, '\t').c_str(), + RegisterGetArraySize(Refl, reg).c_str(), RegisterGetSpaceChar(reg), + reg.BindPoint, reg.Space); + break; + } + + case DxcHLSLNodeType::Variable: + typeToPrint = localId; + break; + + case DxcHLSLNodeType::Function: { + const DxcHLSLFunction &func = Refl.Functions[localId]; + printf("%sreturn: %s, hasDefinition: %s, numParams: %u\n", + std::string(Depth, '\t').c_str(), + func.HasReturn() ? "true" : "false", + func.HasDefinition() ? "true" : "false", func.GetNumParameters()); + + break; + } + + case DxcHLSLNodeType::Enum: + printf("%s: %s\n", std::string(Depth, '\t').c_str(), + EnumTypeToString(Refl.Enums[localId].Type).c_str()); + break; + + case DxcHLSLNodeType::EnumValue: { + printf("%s#%u = %" PRIi64 "\n", std::string(Depth, '\t').c_str(), + IndexInParent, Refl.EnumValues[localId].Value); + break; + } + + //TODO: + case DxcHLSLNodeType::Typedef: + case DxcHLSLNodeType::Using: + break; + + case DxcHLSLNodeType::Namespace: + default: + break; + } + } + + if (typeToPrint != (uint32_t)-1) + RecursePrintType(Refl, typeToPrint, Depth); + + for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) + i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1, j); + + return node.GetChildCount(); +} + +struct DxcHLSLHeader { + + uint32_t MagicNumber; + uint16_t Version; + uint16_t Sources; + + D3D12_HLSL_REFLECTION_FEATURE Features; + uint32_t StringsNonDebug; + + uint32_t Strings; + uint32_t Nodes; + + uint32_t Registers; + uint32_t Functions; + + uint32_t Enums; + uint32_t EnumValues; + + uint32_t Annotations; + uint32_t Arrays; + + uint32_t ArraySizes; + uint32_t Members; + + uint32_t Types; + uint32_t Buffers; +}; + +template +T &UnsafeCast(std::vector &Bytes, uint64_t Offset) { + return *(T *)(Bytes.data() + Offset); +} + +template +const T &UnsafeCast(const std::vector &Bytes, uint64_t Offset) { + return *(const T *)(Bytes.data() + Offset); +} + +template +void SkipPadding(uint64_t& Offset) { + Offset = (Offset + alignof(T) - 1) / alignof(T) * alignof(T); +} + +template +void Skip(uint64_t& Offset, const std::vector& Vec) { + Offset += Vec.size() * sizeof(T); +} + +template +void Advance(uint64_t& Offset, const std::vector& Vec) { + SkipPadding(Offset); + Skip(Offset, Vec); +} + +template <> +void Advance(uint64_t &Offset, + const std::vector &Vec) { + for (const std::string &str : Vec) { + Offset += str.size() >= 128 ? 2 : 1; + Offset += str.size(); + } +} + +template +void Advance(uint64_t& Offset, const std::vector& Vec, const std::vector& Vec2, args... arg) { + Advance(Offset, Vec); + Advance(Offset, Vec2, arg...); +} + +template +void Append(std::vector &Bytes, uint64_t &Offset, + const std::vector &Vec) { + static_assert(std::is_pod_v, "Append only works on POD types"); + SkipPadding(Offset); + std::memcpy(&UnsafeCast(Bytes, Offset), Vec.data(), + Vec.size() * sizeof(T)); + Skip(Offset, Vec); +} + +template <> +void Append(std::vector &Bytes, uint64_t &Offset, + const std::vector &Vec) { + + for (const std::string &str : Vec) { + + if (str.size() >= 128) { + UnsafeCast(Bytes, Offset++) = + (uint8_t)(str.size() & 0x7F) | 0x80; + UnsafeCast(Bytes, Offset++) = (uint8_t)(str.size() >> 7); + } + + else + UnsafeCast(Bytes, Offset++) = (uint8_t)str.size(); + + std::memcpy(&UnsafeCast(Bytes, Offset), str.data(), str.size()); + Offset += str.size(); + } +} + +template +void Append(std::vector &Bytes, uint64_t &Offset, + const std::vector &Vec, const std::vector &Vec2, + args... arg) { + Append(Bytes, Offset, Vec); + Append(Bytes, Offset, Vec2, arg...); +} + +template >> +void Consume(const std::vector &Bytes, uint64_t &Offset, T &t) { + + static_assert(std::is_pod_v, "Consume only works on POD types"); + + SkipPadding(Offset); + + if (Offset + sizeof(T) > Bytes.size()) + throw std::out_of_range("Couldn't consume; out of bounds!"); + + std::memcpy(&t, &UnsafeCast(Bytes, Offset), sizeof(T)); + Offset += sizeof(T); +} + +template +void Consume(const std::vector &Bytes, uint64_t &Offset, T *target, + uint64_t Len) { + + static_assert(std::is_pod_v, "Consume only works on POD types"); + + SkipPadding(Offset); + + if (Offset + sizeof(T) * Len > Bytes.size()) + throw std::out_of_range("Couldn't consume; out of bounds!"); + + std::memcpy(target, &UnsafeCast(Bytes, Offset), sizeof(T) * Len); + Offset += sizeof(T) * Len; +} + +template +void Consume(const std::vector &Bytes, uint64_t &Offset, + std::vector &Vec, uint64_t Len) { + Vec.resize(Len); + Consume(Bytes, Offset, Vec.data(), Len); +} + +template <> +void Consume(const std::vector &Bytes, uint64_t &Offset, + std::vector &Vec, uint64_t Len) { + Vec.resize(Len); + + for (uint64_t i = 0; i < Len; ++i) { + + if (Offset >= Bytes.size()) + throw std::out_of_range("Couldn't consume string len; out of bounds!"); + + uint16_t ourLen = uint8_t(Bytes.at(Offset++)); + + if (ourLen >> 7) { + + if (Offset >= Bytes.size()) + throw std::out_of_range("Couldn't consume string len; out of bounds!"); + + ourLen &= ~(1 << 7); + ourLen |= uint16_t(Bytes.at(Offset++)) << 7; + } + + if (Offset + ourLen > Bytes.size()) + throw std::out_of_range("Couldn't consume string len; out of bounds!"); + + Vec[i].resize(ourLen); + std::memcpy(Vec[i].data(), Bytes.data() + Offset, ourLen); + Offset += ourLen; + } +} + +template +void Consume(const std::vector &Bytes, uint64_t &Offset, + std::vector &Vec, uint64_t Len, std::vector &Vec2, + uint64_t Len2, args&... arg) { + Consume(Bytes, Offset, Vec, Len); + Consume(Bytes, Offset, Vec2, Len2, arg...); +} + +static constexpr uint32_t DxcReflectionDataMagic = DXC_FOURCC('D', 'H', 'R', 'D'); +static constexpr uint16_t DxcReflectionDataVersion = 0; + +void DxcHLSLReflection::StripSymbols() { + Strings.clear(); + StringsToId.clear(); + Sources.clear(); + StringToSourceId.clear(); + FullyResolvedToNodeId.clear(); + NodeIdToFullyResolved.clear(); + FullyResolvedToMemberId.clear(); + NodeSymbols.clear(); + TypeNameIds.clear(); + MemberNameIds.clear(); + Features &= ~D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; +} + +void RecurseNameGenerationType(DxcHLSLReflection &Refl, uint32_t TypeId, + uint32_t LocalId, const std::string &Parent) { + + const DxcHLSLType &type = Refl.Types[TypeId]; + + if (type.Class == D3D_SVC_STRUCT) + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { + + uint32_t memberId = i + type.GetMemberStart(); + std::string memberName = + Parent + "." + Refl.Strings[Refl.MemberNameIds[memberId]]; + + Refl.FullyResolvedToMemberId[memberName] = memberId; + + RecurseNameGenerationType(Refl, Refl.MemberTypeIds[memberId], i, + memberName); + } +} + +uint32_t RecurseNameGeneration(DxcHLSLReflection &Refl, uint32_t NodeId, + uint32_t LocalId, const std::string &Parent, + bool IsDot) { + + const DxcHLSLNode &node = Refl.Nodes[NodeId]; + std::string self = Refl.Strings[Refl.NodeSymbols[NodeId].NameId]; + + if (self.empty() && NodeId) + self = std::to_string(LocalId); + + self = Parent.empty() ? self : Parent + (IsDot ? "." : "::") + self; + Refl.FullyResolvedToNodeId[self] = NodeId; + Refl.NodeIdToFullyResolved[NodeId] = self; + + bool isDotChild = node.GetNodeType() == DxcHLSLNodeType::Register; + bool isVar = node.GetNodeType() == DxcHLSLNodeType::Variable; + + for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) + i += RecurseNameGeneration(Refl, NodeId + 1 + i, j, self, isDotChild); + + if (isVar) { + + uint32_t typeId = node.GetLocalId(); + const DxcHLSLType &type = Refl.Types[typeId]; + + if (type.Class == D3D_SVC_STRUCT) + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { + + uint32_t memberId = i + type.GetMemberStart(); + std::string memberName = + self + "." + Refl.Strings[Refl.MemberNameIds[memberId]]; + + Refl.FullyResolvedToMemberId[memberName] = memberId; + + RecurseNameGenerationType(Refl, Refl.MemberTypeIds[memberId], i, + memberName); + } + } + + return node.GetChildCount(); +} + +bool DxcHLSLReflection::GenerateNameLookupTable() { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) || Nodes.empty()) + return false; + + NodeIdToFullyResolved.resize(Nodes.size()); + RecurseNameGeneration(*this, 0, 0, "", false); + return true; +} + +void DxcHLSLReflection::Dump(std::vector &Bytes) const { + + uint64_t toReserve = sizeof(DxcHLSLHeader); + + Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, + Enums, EnumValues, Annotations, ArraySizes, MemberTypeIds, MemberNameIds, Types, TypeNameIds, Buffers); + + Bytes.resize(toReserve); + + toReserve = 0; + + UnsafeCast(Bytes, toReserve) = { + DxcReflectionDataMagic, DxcReflectionDataVersion, + uint16_t(Sources.size()), Features, + uint32_t(StringsNonDebug.size()), uint32_t(Strings.size()), + uint32_t(Nodes.size()), uint32_t(Registers.size()), + uint32_t(Functions.size()), uint32_t(Enums.size()), + uint32_t(EnumValues.size()), uint32_t(Annotations.size()), + uint32_t(Arrays.size()), uint32_t(ArraySizes.size()), + uint32_t(MemberTypeIds.size()), uint32_t(Types.size()), + uint32_t(Buffers.size())}; + + toReserve += sizeof(DxcHLSLHeader); + + Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, + NodeSymbols, Registers, + Functions, Enums, EnumValues, Annotations, ArraySizes, MemberTypeIds, + MemberNameIds, Types, TypeNameIds, Buffers); +} + +DxcHLSLReflection::DxcHLSLReflection(const std::vector &Bytes, + bool MakeNameLookupTable) { + + uint64_t off = 0; + DxcHLSLHeader header; + Consume(Bytes, off, header); + + if (header.MagicNumber != DxcReflectionDataMagic) + throw std::invalid_argument("Invalid magic number"); + + if (header.Version != DxcReflectionDataVersion) + throw std::invalid_argument("Unrecognized version number"); + + Features = header.Features; + + bool hasSymbolInfo = Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (!hasSymbolInfo && (header.Sources || header.Strings)) + throw std::invalid_argument("Sources are invalid without symbols"); + + uint32_t nodeSymbolCount = hasSymbolInfo ? header.Nodes : 0; + uint32_t memberSymbolCount = hasSymbolInfo ? header.Members : 0; + uint32_t typeSymbolCount = hasSymbolInfo ? header.Types : 0; + + Consume(Bytes, off, Strings, header.Strings, StringsNonDebug, + header.StringsNonDebug, Sources, header.Sources, Nodes, header.Nodes, + NodeSymbols, nodeSymbolCount, Registers, header.Registers, Functions, + header.Functions, Enums, header.Enums, EnumValues, header.EnumValues, + Annotations, header.Annotations, ArraySizes, header.ArraySizes, + MemberTypeIds, header.Members, MemberNameIds, memberSymbolCount, + Types, header.Types, TypeNameIds, typeSymbolCount, Buffers, + header.Buffers); + + // Validation errors are throws to prevent accessing invalid data + + if (off != Bytes.size()) + throw std::invalid_argument("Reflection info had unrecognized data on the back"); + + for(uint32_t i = 0; i < header.Sources; ++i) + if(Sources[i] >= header.Strings) + throw std::invalid_argument("Source path out of bounds"); + + for(uint32_t i = 0; i < header.Nodes; ++i) { + + const DxcHLSLNode &node = Nodes[i]; + + if (hasSymbolInfo && (NodeSymbols[i].NameId >= header.Strings || + (NodeSymbols[i].FileNameId != uint16_t(-1) && + NodeSymbols[i].FileNameId >= header.Sources))) + throw std::invalid_argument("Node " + std::to_string(i) + + " points to invalid name or file name"); + + if( + node.GetAnnotationStart() + node.GetAnnotationCount() > header.Annotations || + node.GetNodeType() > DxcHLSLNodeType::End || + (i && node.GetParentId() >= i) || + i + node.GetChildCount() > header.Nodes + ) + throw std::invalid_argument("Node " + std::to_string(i) + " is invalid"); + + uint32_t maxValue = 1; + + switch(node.GetNodeType()) { + case DxcHLSLNodeType::Register: + maxValue = header.Registers; + break; + case DxcHLSLNodeType::Function: + maxValue = header.Functions; + break; + case DxcHLSLNodeType::Enum: + maxValue = header.Enums; + break; + case DxcHLSLNodeType::EnumValue: + maxValue = header.EnumValues; + break; + case DxcHLSLNodeType::Typedef: + case DxcHLSLNodeType::Using: + case DxcHLSLNodeType::Variable: + maxValue = header.Types; + break; + } + + if(node.GetLocalId() >= maxValue) + throw std::invalid_argument("Node " + std::to_string(i) + " has invalid localId"); + } + + for(uint32_t i = 0; i < header.Registers; ++i) { + + const DxcHLSLRegister ® = Registers[i]; + + if( + reg.NodeId >= header.Nodes || + Nodes[reg.NodeId].GetNodeType() != DxcHLSLNodeType::Register || + Nodes[reg.NodeId].GetLocalId() != i + ) + throw std::invalid_argument("Register " + std::to_string(i) + " points to an invalid nodeId"); + + if (reg.Type > D3D_SIT_UAV_FEEDBACKTEXTURE || + reg.ReturnType > D3D_RETURN_TYPE_CONTINUED || + reg.Dimension > D3D_SRV_DIMENSION_BUFFEREX || !reg.BindCount || + (reg.ArrayId != uint32_t(-1) && reg.ArrayId >= header.Arrays) || + (reg.ArrayId != uint32_t(-1) && reg.BindCount <= 1)) + throw std::invalid_argument( + "Register " + std::to_string(i) + + " invalid type, returnType, bindCount, array or dimension"); + + D3D_CBUFFER_TYPE bufferType = GetBufferType(reg.Type); + + if(bufferType != D3D_CT_INTERFACE_POINTERS) { + + if (reg.BufferId >= header.Buffers || + Buffers[reg.BufferId].NodeId != reg.NodeId || + Buffers[reg.BufferId].Type != bufferType) + throw std::invalid_argument("Register " + std::to_string(i) + + " invalid buffer referenced by register"); + } + } + + for(uint32_t i = 0; i < header.Functions; ++i) { + + const DxcHLSLFunction &func = Functions[i]; + + if (func.NodeId >= header.Nodes || + Nodes[func.NodeId].GetNodeType() != DxcHLSLNodeType::Function || + Nodes[func.NodeId].GetLocalId() != i) + throw std::invalid_argument("Function " + std::to_string(i) + + " points to an invalid nodeId"); + } + + for(uint32_t i = 0; i < header.Enums; ++i) { + + const DxcHLSLEnumDesc &enm = Enums[i]; + + if (enm.NodeId >= header.Nodes || + Nodes[enm.NodeId].GetNodeType() != DxcHLSLNodeType::Enum || + Nodes[enm.NodeId].GetLocalId() != i) + throw std::invalid_argument("Function " + std::to_string(i) + + " points to an invalid nodeId"); + + if (enm.Type < D3D12_HLSL_ENUM_TYPE_START || + enm.Type > D3D12_HLSL_ENUM_TYPE_END) + throw std::invalid_argument("Enum " + std::to_string(i) + + " has an invalid type"); + + const DxcHLSLNode &node = Nodes[enm.NodeId]; + + for (uint32_t j = 0; j < node.GetChildCount(); ++j) { + + const DxcHLSLNode &child = Nodes[enm.NodeId + 1 + j]; + + if (child.GetChildCount() != 0 || + child.GetNodeType() != DxcHLSLNodeType::EnumValue) + throw std::invalid_argument("Enum " + std::to_string(i) + + " has an invalid enum value"); + } + } + + for(uint32_t i = 0; i < header.EnumValues; ++i) { + + const DxcHLSLEnumValue &enumVal = EnumValues[i]; + + if (enumVal.NodeId >= header.Nodes || + Nodes[enumVal.NodeId].GetNodeType() != DxcHLSLNodeType::EnumValue || + Nodes[enumVal.NodeId].GetLocalId() != i || + Nodes[Nodes[enumVal.NodeId].GetParentId()].GetNodeType() != + DxcHLSLNodeType::Enum) + throw std::invalid_argument("Enum " + std::to_string(i) + + " points to an invalid nodeId"); + } + + for (uint32_t i = 0; i < header.Arrays; ++i) { + + const DxcHLSLArray &arr = Arrays[i]; + + if (arr.ArrayElem() <= 1 || arr.ArrayElem() > 8 || + arr.ArrayStart() + arr.ArrayElem() > header.ArraySizes) + throw std::invalid_argument("Array " + std::to_string(i) + + " points to an invalid array element"); + } + + for (uint32_t i = 0; i < header.Annotations; ++i) + if (Annotations[i].GetStringNonDebug() >= header.StringsNonDebug) + throw std::invalid_argument("Annotation " + std::to_string(i) + + " points to an invalid string"); + + for (uint32_t i = 0; i < header.Buffers; ++i) { + + const DxcHLSLBuffer &buf = Buffers[i]; + + if (buf.NodeId >= header.Nodes || + Nodes[buf.NodeId].GetNodeType() != DxcHLSLNodeType::Register || + Nodes[buf.NodeId].GetLocalId() >= header.Registers || + Registers[Nodes[buf.NodeId].GetLocalId()].BufferId != i) + throw std::invalid_argument("Buffer " + std::to_string(i) + + " points to an invalid nodeId"); + + const DxcHLSLNode &node = Nodes[buf.NodeId]; + + if (!node.GetChildCount()) + throw std::invalid_argument("Buffer " + std::to_string(i) + + " requires at least one Variable child"); + + for (uint32_t j = 0; j < node.GetChildCount(); ++j) { + + const DxcHLSLNode &child = Nodes[buf.NodeId + 1 + j]; + + if (child.GetChildCount() != 0 || + child.GetNodeType() != DxcHLSLNodeType::Variable) + throw std::invalid_argument("Buffer " + std::to_string(i) + + " has to have only Variable child nodes"); + } + } + + for (uint32_t i = 0; i < header.Members; ++i) { + + if (MemberTypeIds[i] >= header.Types) + throw std::invalid_argument("Member " + std::to_string(i) + + " points to an invalid type"); + + if (hasSymbolInfo && MemberNameIds[i] >= header.Strings) + throw std::invalid_argument("Member " + std::to_string(i) + + " points to an invalid string"); + } + + for (uint32_t i = 0; i < header.Types; ++i) { + + const DxcHLSLType &type = Types[i]; + + if (hasSymbolInfo && TypeNameIds[i] >= header.Strings) + throw std::invalid_argument("Type " + std::to_string(i) + + " points to an invalid string"); + + if ((type.BaseClass != uint32_t(-1) && type.BaseClass >= header.Types) || + type.GetMemberStart() + type.GetMemberCount() > header.Members || + (type.ElementsOrArrayId >> 31 && + (type.ElementsOrArrayId << 1 >> 1) >= header.Arrays)) + throw std::invalid_argument( + "Type " + std::to_string(i) + + " points to an invalid string, base class or member"); + + switch (type.Class) { + + case D3D_SVC_SCALAR: + + if (type.Columns != 1) + throw std::invalid_argument("Type (scalar) " + std::to_string(i) + + " should have columns == 1"); + + [[fallthrough]]; + + case D3D_SVC_VECTOR: + + if (type.Rows != 1) + throw std::invalid_argument("Type (scalar/vector) " + + std::to_string(i) + + " should have rows == 1"); + + [[fallthrough]]; + + case D3D_SVC_MATRIX_ROWS: + case D3D_SVC_MATRIX_COLUMNS: + + if (!type.Rows || !type.Columns || type.Rows > 128 || type.Columns > 128) + throw std::invalid_argument("Type (scalar/vector/matrix) " + + std::to_string(i) + + " has invalid rows or columns"); + + switch (type.Type) { + case D3D_SVT_BOOL: + case D3D_SVT_INT: + case D3D_SVT_FLOAT: + case D3D_SVT_MIN8FLOAT: + case D3D_SVT_MIN10FLOAT: + case D3D_SVT_MIN16FLOAT: + case D3D_SVT_MIN12INT: + case D3D_SVT_MIN16INT: + case D3D_SVT_MIN16UINT: + case D3D_SVT_INT16: + case D3D_SVT_UINT16: + case D3D_SVT_FLOAT16: + case D3D_SVT_INT64: + case D3D_SVT_UINT64: + case D3D_SVT_UINT: + case D3D_SVT_DOUBLE: + break; + + default: + throw std::invalid_argument("Type (scalar/matrix/vector) " + + std::to_string(i) + + " is of invalid type"); + } + + break; + + case D3D_SVC_STRUCT: + + if (!type.GetMemberCount()) + throw std::invalid_argument("Type (struct) " + std::to_string(i) + + " is missing children"); + if (type.Type) + throw std::invalid_argument("Type (struct) " + + std::to_string(i) + + " shouldn't have rows or columns"); + + if (type.Rows || type.Columns) + throw std::invalid_argument("Type (struct) " + + std::to_string(i) + + " shouldn't have rows or columns"); + + break; + + case D3D_SVC_OBJECT: + + switch (type.Type) { + + case D3D_SVT_STRING: + case D3D_SVT_TEXTURE1D: + case D3D_SVT_TEXTURE2D: + case D3D_SVT_TEXTURE3D: + case D3D_SVT_TEXTURECUBE: + case D3D_SVT_SAMPLER: + case D3D_SVT_BUFFER: + case D3D_SVT_CBUFFER: + case D3D_SVT_TBUFFER: + case D3D_SVT_TEXTURE1DARRAY: + case D3D_SVT_TEXTURE2DARRAY: + case D3D_SVT_TEXTURE2DMS: + case D3D_SVT_TEXTURE2DMSARRAY: + case D3D_SVT_TEXTURECUBEARRAY: + case D3D_SVT_RWTEXTURE1D: + case D3D_SVT_RWTEXTURE1DARRAY: + case D3D_SVT_RWTEXTURE2D: + case D3D_SVT_RWTEXTURE2DARRAY: + case D3D_SVT_RWTEXTURE3D: + case D3D_SVT_RWBUFFER: + case D3D_SVT_BYTEADDRESS_BUFFER: + case D3D_SVT_RWBYTEADDRESS_BUFFER: + case D3D_SVT_STRUCTURED_BUFFER: + case D3D_SVT_RWSTRUCTURED_BUFFER: + case D3D_SVT_APPEND_STRUCTURED_BUFFER: + case D3D_SVT_CONSUME_STRUCTURED_BUFFER: + break; + + default: + throw std::invalid_argument("Type (object) " + std::to_string(i) + + " is of invalid type"); + } + + if (type.Rows || type.Columns) + throw std::invalid_argument("Type (object) " + + std::to_string(i) + + " shouldn't have rows or columns"); + + break; + + default: + throw std::invalid_argument("Type " + std::to_string(i) + + " has an invalid class"); + } + } + + if (MakeNameLookupTable) + GenerateNameLookupTable(); +}; + + +void DxcHLSLReflection::Printf() const { RecursePrint(*this, 0, 0, 0); } + +} diff --git a/tools/clang/tools/libclang/CMakeLists.txt b/tools/clang/tools/libclang/CMakeLists.txt index ed49cbaf44..724d24ccc8 100644 --- a/tools/clang/tools/libclang/CMakeLists.txt +++ b/tools/clang/tools/libclang/CMakeLists.txt @@ -179,6 +179,7 @@ endif() endif() # HLSL Change add_dependencies(libclang TablegenHLSLOptions) # HLSL Change +target_link_libraries(libclang PRIVATE dxcreflection) # HLSL Change # HLSL Change Starts # add_clang_library(${LIBCLANG_STATIC_TARGET_NAME} STATIC ${SOURCES}) diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 0bf8ccdea5..926a96e3b4 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -12,7 +12,6 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/HlslTypes.h" -#include "clang/AST/Attr.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" @@ -46,7 +45,7 @@ #include "dxc/dxcapi.internal.h" #include "dxc/dxctools.h" -#include "d3d12shader.h" +#include "dxc/DxcReflection/DxcReflection.h" // From dxcutil.h namespace dxcutil { @@ -1278,2721 +1277,22 @@ static void GenerateConsistentBindings(DeclContext &Ctx, } } -enum class DxcHLSLNodeType : uint64_t { - Register, - Function, - Enum, - EnumValue, - Namespace, - Typedef, - Using, - Variable, //localId points to the type for a variable - Parameter, - Type, - - Start = Register, - End = Type -}; - -struct DxcHLSLNodeSymbol { - - union { - struct { - uint32_t NameId; // Local name (not including parent's name) - - uint16_t FileNameId; //-1 == no file info - uint16_t SourceLineCount; - }; - uint64_t NameIdFileNameIdSourceLineCount; - }; - - union { - struct { - uint16_t SourceColumnStartLo; - uint16_t SourceColumnEndLo; - uint32_t ColumnHiSourceLinePad; // 2 : 20 : 10 - }; - uint64_t SourceColumnStartEndLo; - }; - - DxcHLSLNodeSymbol() = default; - - DxcHLSLNodeSymbol(uint32_t NameId, uint16_t FileNameId, - uint16_t SourceLineCount, uint32_t SourceLineStart, - uint32_t SourceColumnStart, uint32_t SourceColumnEnd) - : NameId(NameId), FileNameId(FileNameId), - SourceLineCount(SourceLineCount), - SourceColumnStartLo(uint16_t(SourceColumnStart)), - SourceColumnEndLo(uint16_t(SourceColumnEnd)), - ColumnHiSourceLinePad((SourceColumnStart >> 16) | - (SourceColumnEnd >> 16 << 1) | - (SourceLineStart << 2)) { - - assert(SourceColumnStart < (1 << 17) && "SourceColumnStart out of bounds"); - assert(SourceColumnEnd < (1 << 17) && "SourceColumnEnd out of bounds"); - - assert(SourceLineStart < ((1 << 20) - 1) && - "SourceLineStart out of bounds"); - } - - uint32_t GetSourceLineStart() const { - return uint32_t(ColumnHiSourceLinePad >> 2); - } - - uint32_t GetSourceColumnStart() const { - return SourceColumnStartLo | ((ColumnHiSourceLinePad & 1) << 16); - } - - uint32_t GetSourceColumnEnd() const { - return SourceColumnEndLo | ((ColumnHiSourceLinePad & 2) << 15); - } - - bool operator==(const DxcHLSLNodeSymbol &other) const { - return NameIdFileNameIdSourceLineCount == - other.NameIdFileNameIdSourceLineCount && - SourceColumnStartEndLo == other.SourceColumnStartEndLo; - } -}; - -struct DxcHLSLNode { - - uint32_t LocalIdParentLo; //24 : 8 - uint32_t ParentHiAnnotationsType; //16 : 10 : 6 - uint32_t ChildCountPad; //24 : 8 - uint32_t AnnotationStartPad; //20 : 12 - - DxcHLSLNode() = default; - - DxcHLSLNode(DxcHLSLNodeType NodeType, uint32_t LocalId, - uint32_t AnnotationStart, uint32_t ChildCount, uint32_t ParentId, - uint16_t AnnotationCount) - : LocalIdParentLo(LocalId | (ParentId << 24)), - ChildCountPad(ChildCount), - AnnotationStartPad(AnnotationStart), - ParentHiAnnotationsType( - (uint32_t(NodeType) << 26) | - (uint32_t(AnnotationCount) << 16) | - (ParentId >> 8)) { - - assert(NodeType >= DxcHLSLNodeType::Start && - NodeType <= DxcHLSLNodeType::End && "Invalid enum value"); - - assert(LocalId < ((1 << 24) - 1) && "LocalId out of bounds"); - assert(ParentId < ((1 << 24) - 1) && "ParentId out of bounds"); - assert(ChildCount < ((1 << 24) - 1) && "ChildCount out of bounds"); - assert(AnnotationCount < (1 << 10) && "AnnotationCount out of bounds"); - - assert(AnnotationStart < ((1 << 20) - 1) && - "AnnotationStart out of bounds"); - } - - // For example if Enum, maps into Enums[LocalId] - uint32_t GetLocalId() const { return LocalIdParentLo << 8 >> 8; } - uint32_t GetAnnotationStart() const { return AnnotationStartPad; } - - DxcHLSLNodeType GetNodeType() const { - return DxcHLSLNodeType(ParentHiAnnotationsType >> 26); - } - - // Includes recursive children - uint32_t GetChildCount() const { return ChildCountPad; } - - uint32_t GetAnnotationCount() const { - return uint32_t(ParentHiAnnotationsType << 6 >> (32 - 10)); - } - - uint32_t GetParentId() const { - return uint32_t(LocalIdParentLo >> 24) | uint32_t(ParentHiAnnotationsType << 16 >> 16); - } - - void IncreaseChildCount() { - assert(ChildCountPad < ((1 << 24) - 1) && "Child count out of bounds"); - ++ChildCountPad; - } - - bool operator==(const DxcHLSLNode &other) const { - return LocalIdParentLo == other.LocalIdParentLo && - ParentHiAnnotationsType == other.ParentHiAnnotationsType && - ChildCountPad == other.ChildCountPad; - } -}; - -struct DxcHLSLEnumDesc { - - uint32_t NodeId; - D3D12_HLSL_ENUM_TYPE Type; - - bool operator==(const DxcHLSLEnumDesc &other) const { - return NodeId == other.NodeId && Type == other.Type; - } -}; - -struct DxcHLSLEnumValue { - - int64_t Value; - uint32_t NodeId; - - bool operator==(const DxcHLSLEnumValue &other) const { - return Value == other.Value && - NodeId == other.NodeId; - } -}; - -struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC (ex. - // First(In/Out)(Register/Component)), but with - // std::string and NodeId - - std::string SemanticName; - D3D_SHADER_VARIABLE_TYPE Type; // Element type. - D3D_SHADER_VARIABLE_CLASS Class; // Scalar/Vector/Matrix. - uint32_t Rows; // Rows are for matrix parameters. - uint32_t Columns; // Components or Columns in matrix. - D3D_INTERPOLATION_MODE InterpolationMode; // Interpolation mode. - D3D_PARAMETER_FLAGS Flags; // Parameter modifiers. - uint32_t NodeId; - - // TODO: Array info -}; - -struct DxcHLSLFunction { - - uint32_t NodeId; - uint32_t NumParametersHasReturnAndDefinition; - - DxcHLSLFunction() = default; - - DxcHLSLFunction(uint32_t NodeId, uint32_t NumParameters, bool HasReturn, - bool HasDefinition) - : NodeId(NodeId), - NumParametersHasReturnAndDefinition(NumParameters | - (HasReturn ? (1 << 30) : 0) | - (HasDefinition ? (1 << 31) : 0)) { - - assert(NumParameters < (1 << 30) && "NumParameters out of bounds"); - } - - uint32_t GetNumParameters() const { - return NumParametersHasReturnAndDefinition << 2 >> 2; - } - - bool HasReturn() const { - return (NumParametersHasReturnAndDefinition >> 30) & 1; - } - - bool HasDefinition() const { - return (NumParametersHasReturnAndDefinition >> 31) & 1; - } - - bool operator==(const DxcHLSLFunction &other) const { - return NodeId == other.NodeId && - NumParametersHasReturnAndDefinition == - other.NumParametersHasReturnAndDefinition; - } -}; - -struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus - // the Name (and uID replaced with NodeID) and added - // arrayIndex and better packing - - union { - struct { - uint8_t Type; // D3D_SHADER_INPUT_TYPE - uint8_t Dimension; // D3D_SRV_DIMENSION - uint8_t ReturnType; // D3D_RESOURCE_RETURN_TYPE - uint8_t uFlags; - - uint32_t BindPoint; - }; - uint64_t TypeDimensionReturnTypeFlagsBindPoint; - }; - - union { - struct { - uint32_t Space; - uint32_t BindCount; - }; - uint64_t SpaceBindCount; - }; - - union { - struct { - uint32_t NumSamples; - uint32_t NodeId; - }; - uint64_t NumSamplesNodeId; - }; - - union { - struct { - uint32_t ArrayId; // Only if BindCount > 1 and the array is 2D+ (else -1) - uint32_t BufferId; // If cbuffer or structured buffer - }; - uint64_t ArrayIdBufferId; - }; - - DxcHLSLRegister() = default; - DxcHLSLRegister(D3D_SHADER_INPUT_TYPE Type, uint32_t BindPoint, - uint32_t BindCount, uint32_t uFlags, - D3D_RESOURCE_RETURN_TYPE ReturnType, - D3D_SRV_DIMENSION Dimension, uint32_t NumSamples, - uint32_t Space, uint32_t NodeId, uint32_t ArrayId, - uint32_t BufferId) - : Type(Type), BindPoint(BindPoint), BindCount(BindCount), uFlags(uFlags), - ReturnType(ReturnType), Dimension(Dimension), - NumSamples(NumSamples), Space(Space), NodeId(NodeId), - ArrayId(ArrayId), BufferId(BufferId) { - - assert(Type >= D3D_SIT_CBUFFER && Type <= D3D_SIT_UAV_FEEDBACKTEXTURE && - "Invalid type"); - - assert(ReturnType >= 0 && ReturnType <= D3D_RETURN_TYPE_CONTINUED && - "Invalid return type"); - - assert(Dimension >= D3D_SRV_DIMENSION_UNKNOWN && - Dimension <= D3D_SRV_DIMENSION_BUFFEREX && "Invalid srv dimension"); - - assert(!(uFlags >> 8) && "Invalid user flags"); - } - - bool operator==(const DxcHLSLRegister &other) const { - return TypeDimensionReturnTypeFlagsBindPoint == - other.TypeDimensionReturnTypeFlagsBindPoint && - SpaceBindCount == other.SpaceBindCount && - NumSamplesNodeId == other.NumSamplesNodeId && - ArrayIdBufferId == other.ArrayIdBufferId; - } -}; - -struct DxcHLSLArray { - - uint32_t ArrayElemStart; - - DxcHLSLArray() = default; - DxcHLSLArray(uint32_t ArrayElem, uint32_t ArrayStart) - : ArrayElemStart((ArrayElem << 28) | ArrayStart) { - - assert(ArrayElem <= 8 && ArrayElem > 1 && "ArrayElem out of bounds"); - assert(ArrayStart < (1 << 28) && "ArrayStart out of bounds"); - } - - bool operator==(const DxcHLSLArray &Other) const { - return Other.ArrayElemStart == ArrayElemStart; - } - - uint32_t ArrayElem() const { return ArrayElemStart >> 28; } - uint32_t ArrayStart() const { return ArrayElemStart << 4 >> 4; } -}; - -using DxcHLSLMember = uint32_t; //typeId - -struct DxcHLSLType { // Almost maps to CShaderReflectionType and - // D3D12_SHADER_TYPE_DESC, but tightly packed and - // easily serializable - union { - struct { - uint32_t MemberData; //24 : 8 (start, count) - uint8_t Class; // D3D_SHADER_VARIABLE_CLASS - uint8_t Type; // D3D_SHADER_VARIABLE_TYPE - uint8_t Rows; - uint8_t Columns; - }; - uint64_t MemberDataClassTypeRowsColums; - }; - - union { - struct { - uint32_t ElementsOrArrayId; - uint32_t BaseClass; // -1 if none, otherwise a type index - }; - uint64_t ElementsOrArrayIdBaseClass; - }; - - bool operator==(const DxcHLSLType &Other) const { - return Other.MemberDataClassTypeRowsColums == - MemberDataClassTypeRowsColums && - ElementsOrArrayIdBaseClass == Other.ElementsOrArrayIdBaseClass; - } - - uint32_t GetMemberCount() const { return MemberData >> 24; } - uint32_t GetMemberStart() const { return MemberData << 8 >> 8; } - - bool IsMultiDimensionalArray() const { return ElementsOrArrayId >> 31; } - bool IsArray() const { return ElementsOrArrayId; } - bool Is1DArray() const { return IsArray() && !IsMultiDimensionalArray(); } - - uint32_t Get1DElements() const { - return IsMultiDimensionalArray() ? 0 : ElementsOrArrayId; - } - - uint32_t GetMultiDimensionalArrayId() const { - return IsMultiDimensionalArray() ? (ElementsOrArrayId << 1 >> 1) - : (uint32_t)-1; - } - - DxcHLSLType() = default; - DxcHLSLType(uint32_t BaseClass, uint32_t ElementsOrArrayId, - D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE Type, - uint8_t Rows, uint8_t Columns, uint32_t MembersCount, - uint32_t MembersStart) - : MemberData(MembersStart | (MembersCount << 24)), - Class(Class), Type(Type), Rows(Rows), Columns(Columns), - ElementsOrArrayId(ElementsOrArrayId), BaseClass(BaseClass) { - - assert(Class >= D3D_SVC_SCALAR && Class <= D3D_SVC_INTERFACE_POINTER && - "Invalid class"); - assert(Type >= D3D_SVT_VOID && Type <= D3D_SVT_UINT64 && "Invalid type"); - assert(MembersStart < (1 << 24) && "Member start out of bounds"); - assert(MembersCount < (1 << 8) && "Member count out of bounds"); - } -}; - -struct DxcRegisterTypeInfo { - D3D_SHADER_INPUT_TYPE RegisterType; - D3D_SHADER_INPUT_FLAGS RegisterFlags; - D3D_SRV_DIMENSION TextureDimension; - D3D_RESOURCE_RETURN_TYPE TextureValue; - uint32_t SampleCount; -}; - -struct DxcHLSLBuffer { // Almost maps to CShaderReflectionConstantBuffer and - // D3D12_SHADER_BUFFER_DESC - - D3D_CBUFFER_TYPE Type; - uint32_t NodeId; - - bool operator==(const DxcHLSLBuffer &other) const { - return Type == other.Type && NodeId == other.NodeId; - } -}; - -struct DxcHLSLAnnotation { - - uint32_t StringNonDebugAndIsBuiltin; - - DxcHLSLAnnotation() = default; - - DxcHLSLAnnotation(uint32_t StringNonDebug, bool IsBuiltin) - : StringNonDebugAndIsBuiltin(StringNonDebug | - (IsBuiltin ? (1u << 31) : 0)) { - assert(StringNonDebug < (1u << 31) && "String non debug out of bounds"); - } - - bool operator==(const DxcHLSLAnnotation &other) const { - return StringNonDebugAndIsBuiltin == other.StringNonDebugAndIsBuiltin; - } - - bool GetIsBuiltin() const { return StringNonDebugAndIsBuiltin >> 31; } - uint32_t GetStringNonDebug() const { - return StringNonDebugAndIsBuiltin << 1 >> 1; - } -}; - -struct DxcReflectionData { - - D3D12_HLSL_REFLECTION_FEATURE Features; - - std::vector Strings; - std::unordered_map StringsToId; - - std::vector StringsNonDebug; - std::unordered_map StringsToIdNonDebug; - - std::vector Sources; - std::unordered_map StringToSourceId; - - std::vector Nodes; // 0 = Root node (global scope) - - std::vector Registers; - std::vector Functions; - - std::vector Enums; - std::vector EnumValues; - - // std::vector Parameters; - std::vector Annotations; - - std::vector Arrays; - std::vector ArraySizes; - - std::vector MemberTypeIds; - std::vector Types; - std::vector Buffers; - - //Can be stripped if !(D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) - - std::vector NodeSymbols; - std::vector MemberNameIds; - std::vector TypeNameIds; - - std::unordered_map FullyResolvedToNodeId; - std::vector NodeIdToFullyResolved; - std::unordered_map FullyResolvedToMemberId; - - void Dump(std::vector &Bytes) const; - void StripSymbols(); - bool GenerateNameLookupTable(); - - DxcReflectionData() = default; - DxcReflectionData(const std::vector &Bytes, bool MakeNameLookupTable); - - bool IsSameNonDebug(const DxcReflectionData &other) const { - return StringsNonDebug == other.StringsNonDebug && Nodes == other.Nodes && - Registers == other.Registers && Functions == other.Functions && - Enums == other.Enums && EnumValues == other.EnumValues && - Annotations == other.Annotations && Arrays == other.Arrays && - ArraySizes == other.ArraySizes && - MemberTypeIds == other.MemberTypeIds && Types == other.Types && - Buffers == other.Buffers; - } - - bool operator==(const DxcReflectionData &other) const { - return IsSameNonDebug(other) && Strings == other.Strings && - Sources == other.Sources && NodeSymbols == other.NodeSymbols && - MemberNameIds == other.MemberNameIds && - TypeNameIds == other.TypeNameIds; - } -}; - -static uint32_t RegisterString(DxcReflectionData &Refl, - const std::string &Name, bool isNonDebug) { - - assert(Name.size() < 32768 && "Strings are limited to 32767"); - - if (isNonDebug) { - - assert(Refl.StringsNonDebug.size() < (uint32_t)-1 && "Strings overflow"); - - auto it = Refl.StringsToIdNonDebug.find(Name); - - if (it != Refl.StringsToIdNonDebug.end()) - return it->second; - - uint32_t stringId = (uint32_t)Refl.StringsNonDebug.size(); - - Refl.StringsNonDebug.push_back(Name); - Refl.StringsToIdNonDebug[Name] = stringId; - return stringId; - } - - assert(Refl.Strings.size() < (uint32_t)-1 && "Strings overflow"); - - auto it = Refl.StringsToId.find(Name); - - if (it != Refl.StringsToId.end()) - return it->second; - - uint32_t stringId = (uint32_t) Refl.Strings.size(); - - Refl.Strings.push_back(Name); - Refl.StringsToId[Name] = stringId; - return stringId; -} - -static uint32_t PushNextNodeId(DxcReflectionData &Refl, const SourceManager &SM, - const LangOptions &LangOpts, - const std::string &UnqualifiedName, Decl *Decl, - DxcHLSLNodeType Type, uint32_t ParentNodeId, - uint32_t LocalId, const SourceRange *Range = nullptr) { - - assert(Refl.Nodes.size() < (uint32_t)(1 << 24) && "Nodes overflow"); - assert(LocalId < (uint32_t)(1 << 24) && "LocalId overflow"); - - uint32_t nodeId = Refl.Nodes.size(); - - uint32_t annotationStart = (uint32_t) Refl.Annotations.size(); - uint16_t annotationCount = 0; - - if (Decl) { - for (const Attr *attr : Decl->attrs()) { - if (const AnnotateAttr *annotate = dyn_cast(attr)) { - - assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); - - Refl.Annotations.push_back(DxcHLSLAnnotation( - RegisterString(Refl, annotate->getAnnotation().str(), true), - false)); - - assert(annotationCount != uint16_t(-1) && - "Annotation count out of bounds"); - ++annotationCount; - - } else if (const HLSLShaderAttr *shaderAttr = - dyn_cast(attr)) { - - assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); - - Refl.Annotations.push_back(DxcHLSLAnnotation( - RegisterString( - Refl, "shader(\"" + shaderAttr->getStage().str() + "\")", true), - true)); - - assert(annotationCount != uint16_t(-1) && - "Annotation count out of bounds"); - ++annotationCount; - } - } - } - - if (Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { - - uint16_t sourceLineCount = 0; - uint32_t sourceLineStart = 0; - uint32_t sourceColumnStart = 0; - uint32_t sourceColumnEnd = 0; - - uint16_t fileNameId = (uint16_t)-1; - - SourceRange range = - Decl ? Decl->getSourceRange() : (Range ? *Range : SourceRange()); - - SourceLocation start = range.getBegin(); - SourceLocation end = range.getEnd(); - - if (start.isValid() && end.isValid()) { - - PresumedLoc presumed = SM.getPresumedLoc(start); - - SourceLocation realEnd = SM.getFileLoc(end); - SourceLocation endOfToken = - Lexer::getLocForEndOfToken(realEnd, 0, SM, LangOpts); - PresumedLoc presumedEnd = SM.getPresumedLoc(endOfToken); - - if (presumed.isValid() && presumedEnd.isValid()) { - - uint32_t startLine = presumed.getLine(); - uint32_t startCol = presumed.getColumn(); - uint32_t endLine = presumedEnd.getLine(); - uint32_t endCol = presumedEnd.getColumn(); - - std::string fileName = presumed.getFilename(); - - assert(fileName == presumedEnd.getFilename() && - "End and start are not in the same file"); - - auto it = Refl.StringToSourceId.find(fileName); - uint32_t i; - - if (it == Refl.StringToSourceId.end()) { - i = (uint32_t)Refl.Sources.size(); - Refl.Sources.push_back(RegisterString(Refl, fileName, false)); - Refl.StringToSourceId[fileName] = i; - } - - else { - i = it->second; - } - - assert(i < 65535 && "Source file count is limited to 16-bit"); - assert((endLine - startLine) < 65535 && - "Source line count is limited to 16-bit"); - assert(startLine < 1048576 && "Source line start is limited to 20-bit"); - assert(startCol < 131072 && "Column start is limited to 17-bit"); - assert(endCol < 131072 && "Column end is limited to 17-bit"); - - sourceLineCount = uint16_t(endLine - startLine + 1); - sourceLineStart = startLine; - sourceColumnStart = startCol; - sourceColumnEnd = endCol; - fileNameId = (uint16_t)i; - } - } - - uint32_t nameId = RegisterString(Refl, UnqualifiedName, false); - - Refl.NodeSymbols.push_back( - DxcHLSLNodeSymbol(nameId, fileNameId, sourceLineCount, sourceLineStart, - sourceColumnStart, sourceColumnEnd)); - } - - Refl.Nodes.push_back(DxcHLSLNode{Type, LocalId, annotationStart, 0, - ParentNodeId, annotationCount}); - - uint32_t parentParent = ParentNodeId; - - while (parentParent != 0) { - DxcHLSLNode &parent = Refl.Nodes[parentParent]; - parent.IncreaseChildCount(); - parentParent = parent.GetParentId(); - } - - Refl.Nodes[0].IncreaseChildCount(); - - return nodeId; -} - -static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, - std::string TypeName, - bool IsWrite, - const CXXRecordDecl *RecordDecl) { - - DxcRegisterTypeInfo type = {}; - type.RegisterType = IsWrite ? D3D_SIT_UAV_RWTYPED : D3D_SIT_TEXTURE; - type.SampleCount = (uint32_t)-1; - - //Parse return type and dimensions - - const ClassTemplateSpecializationDecl *textureTemplate = - dyn_cast(RecordDecl); - - assert(textureTemplate && "Expected texture template"); - - const ArrayRef& textureParams = textureTemplate->getTemplateArgs().asArray(); - - assert(textureParams.size() == 1 && !textureParams[0].getAsType().isNull() && - "Expected template args"); - - QualType valueType = textureParams[0].getAsType(); - QualType desugared = valueType.getDesugaredType(ASTCtx); - - const RecordType *RT = desugared->getAs(); - assert(RT && "Expected record type"); - - const CXXRecordDecl *RD = dyn_cast(RT->getDecl()); - assert(RT && "Expected record decl"); - - const ClassTemplateSpecializationDecl *vectorType = - dyn_cast(RD); - - assert(vectorType && - "Expected vector type as template inside of texture template"); - - const ArrayRef &vectorParams = - vectorType->getTemplateArgs().asArray(); - - assert(vectorParams.size() == 2 && !vectorParams[0].getAsType().isNull() && - vectorParams[1].getKind() == TemplateArgument::Integral && - "Expected vector to be vector"); - - valueType = vectorParams[0].getAsType(); - desugared = valueType.getDesugaredType(ASTCtx); - - if (desugared->isFloatingType()) { - type.TextureValue = desugared->isSpecificBuiltinType(BuiltinType::Double) - ? D3D_RETURN_TYPE_DOUBLE - : D3D_RETURN_TYPE_FLOAT; - } else if (desugared->isIntegerType()) { - const auto &semantics = ASTCtx.getTypeInfo(desugared); - if (semantics.Width == 64) { - type.TextureValue = D3D_RETURN_TYPE_MIXED; - } else { - type.TextureValue = desugared->isUnsignedIntegerType() - ? D3D_RETURN_TYPE_UINT - : D3D_RETURN_TYPE_SINT; - } - } - - else { - type.TextureValue = D3D_RETURN_TYPE_MIXED; - } - - switch (vectorParams[1].getAsIntegral().getZExtValue()) { - case 2: - type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENT_0; - break; - case 3: - type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENT_1; - break; - case 4: - type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENTS; - break; - } - - //Parse type - - if (TypeName == "Buffer") { - type.TextureDimension = D3D_SRV_DIMENSION_BUFFER; - return type; - } - - bool isFeedback = false; - - if (TypeName.size() > 8 && TypeName.substr(0, 8) == "Feedback") { - isFeedback = true; - TypeName = TypeName.substr(8); - type.RegisterType = D3D_SIT_UAV_FEEDBACKTEXTURE; - } - - bool isArray = false; - - if (TypeName.size() > 5 && TypeName.substr(TypeName.size() - 5) == "Array") { - isArray = true; - TypeName = TypeName.substr(0, TypeName.size() - 5); - } - - if (TypeName == "Texture2D") - type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2D; - - else if (TypeName == "TextureCube") - type.TextureDimension = D3D_SRV_DIMENSION_TEXTURECUBE; - - else if (TypeName == "Texture3D") - type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE3D; - - else if (TypeName == "Texture1D") - type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE1D; - - else if (TypeName == "Texture2DMS") { - type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2DMS; - type.SampleCount = 0; - } - - if (isArray) //Arrays are always 1 behind the regular type - type.TextureDimension = (D3D_SRV_DIMENSION)(type.TextureDimension + 1); - - return type; -} - -static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, - QualType Type) { - - QualType realType = Type.getDesugaredType(ASTCtx); - const RecordType *RT = realType->getAs(); - assert(RT && "GetRegisterTypeInfo() type is not a RecordType"); - - const CXXRecordDecl *recordDecl = RT->getAsCXXRecordDecl(); - assert(recordDecl && "GetRegisterTypeInfo() type is not a CXXRecordDecl"); - - std::string typeName = recordDecl->getNameAsString(); - - if (typeName.size() >= 17 && - typeName.substr(0, 17) == "RasterizerOrdered") { - typeName = typeName.substr(17); - } - - if (typeName == "SamplerState" || typeName == "SamplerComparisonState") { - return {D3D_SIT_SAMPLER, typeName == "SamplerComparisonState" - ? D3D_SIF_COMPARISON_SAMPLER - : (D3D_SHADER_INPUT_FLAGS)0}; - } - - DxcRegisterTypeInfo info = {}; - - if (const ClassTemplateSpecializationDecl *spec = - dyn_cast(recordDecl)) { - - const ArrayRef &array = - spec->getTemplateArgs().asArray(); - - if (array.size() == 1) - info.SampleCount = (uint32_t) (ASTCtx.getTypeSize(array[0].getAsType()) / 8); - } - - if (typeName == "AppendStructuredBuffer") { - info.RegisterType = D3D_SIT_UAV_APPEND_STRUCTURED; - return info; - } - - if (typeName == "ConsumeStructuredBuffer") { - info.RegisterType = D3D_SIT_UAV_CONSUME_STRUCTURED; - return info; - } - - if (typeName == "RaytracingAccelerationStructure") { - info.RegisterType = D3D_SIT_RTACCELERATIONSTRUCTURE; - info.SampleCount = (uint32_t)-1; - return info; - } - - if (typeName == "TextureBuffer") { - info.RegisterType = D3D_SIT_TBUFFER; - return info; - } - - if (typeName == "ConstantBuffer") { - info.RegisterType = D3D_SIT_CBUFFER; - return info; - } - - bool isWrite = - typeName.size() > 2 && typeName[0] == 'R' && typeName[1] == 'W'; - - if (isWrite) - typeName = typeName.substr(2); - - if (typeName == "StructuredBuffer") { - info.RegisterType = - isWrite ? D3D_SIT_UAV_RWSTRUCTURED : D3D_SIT_STRUCTURED; - return info; - } - - if (typeName == "ByteAddressBuffer") { - info.RegisterType = - isWrite ? D3D_SIT_UAV_RWBYTEADDRESS : D3D_SIT_BYTEADDRESS; - return info; - } - - return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); -} - -static uint32_t PushArray(DxcReflectionData &Refl, uint32_t ArraySizeFlat, - const std::vector &ArraySize) { - - if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) - return (uint32_t)-1; - - assert(Refl.Arrays.size() < (uint32_t)((1u << 31) - 1) && "Arrays would overflow"); - uint32_t arrayId = (uint32_t)Refl.Arrays.size(); - - uint32_t arrayCountStart = (uint32_t)Refl.ArraySizes.size(); - uint32_t numArrayElements = std::min((size_t)8, ArraySize.size()); - assert(Refl.ArraySizes.size() + numArrayElements < ((1 << 28) - 1) && - "Array elements would overflow"); - - for (uint32_t i = 0; i < ArraySize.size() && i < 8; ++i) { - - uint32_t arraySize = ArraySize[i]; - - // Flatten rest of array to at least keep consistent array elements - if (i == 7) - for (uint32_t j = i + 1; j < ArraySize.size(); ++j) - arraySize *= ArraySize[j]; - - Refl.ArraySizes.push_back(arraySize); - } - - DxcHLSLArray arr = {numArrayElements, arrayCountStart}; - - for (uint32_t i = 0; i < Refl.Arrays.size(); ++i) - if (Refl.Arrays[i] == arr) - return i; - - Refl.Arrays.push_back(arr); - return arrayId; -} - -uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcReflectionData &Refl, - QualType Original, bool DefaultRowMaj) { - - // Unwrap array - - uint32_t arraySize = 1; - QualType underlying = Original, forName = Original; - std::vector arrayElem; - - while (const ConstantArrayType *arr = - dyn_cast(underlying)) { - uint32_t current = arr->getSize().getZExtValue(); - arrayElem.push_back(current); - arraySize *= arr->getSize().getZExtValue(); - forName = arr->getElementType(); - underlying = forName.getCanonicalType(); - } - - underlying = underlying.getCanonicalType(); - - // Name; Omit struct, class and const keywords - - PrintingPolicy policy(ASTCtx.getLangOpts()); - policy.SuppressScope = false; - policy.AnonymousTagLocations = false; - policy.SuppressTagKeyword = true; - - bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - uint32_t nameId = - hasSymbols - ? RegisterString( - Refl, forName.getLocalUnqualifiedType().getAsString(policy), - false) - : uint32_t(-1); - - uint32_t arrayId = PushArray(Refl, arraySize, arrayElem); - uint32_t elementsOrArrayId = 0; - - if (arrayId != (uint32_t)-1) - elementsOrArrayId = (1u << 31) | arrayId; - - else - elementsOrArrayId = arraySize > 1 ? arraySize : 0; - - //Unwrap vector and matrix - //And base type - - D3D_SHADER_VARIABLE_CLASS cls = D3D_SVC_STRUCT; - uint8_t rows = 0, columns = 0; - - uint32_t membersCount = 0; - uint32_t membersOffset = 0; - - uint32_t baseType = uint32_t(-1); - - if (const RecordType *record = underlying->getAs()) { - - bool standardType = false; - - RecordDecl *recordDecl = record->getDecl(); - - if (const ClassTemplateSpecializationDecl *templateClass = - dyn_cast(recordDecl)) { - - const std::string &name = templateClass->getIdentifier()->getName(); - - const ArrayRef ¶ms = - templateClass->getTemplateArgs().asArray(); - - uint32_t magic = 0; - std::memcpy(&magic, name.c_str(), std::min(sizeof(magic), name.size())); - - std::string_view subs = - name.size() < sizeof(magic) - ? std::string_view() - : std::string_view(name).substr(sizeof(magic)); - - switch (magic) { - - case DXC_FOURCC('v', 'e', 'c', 't'): - - if (subs == "or") { - - rows = 1; - - assert(params.size() == 2 && !params[0].getAsType().isNull() && - params[1].getKind() == TemplateArgument::Integral && - "Expected vector to be vector"); - - underlying = params[0].getAsType(); - columns = params[1].getAsIntegral().getSExtValue(); - cls = D3D_SVC_VECTOR; - standardType = true; - } - - break; - - case DXC_FOURCC('m', 'a', 't', 'r'): - - if (subs == "ix") { - - assert(params.size() == 3 && !params[0].getAsType().isNull() && - params[1].getKind() == TemplateArgument::Integral && - params[2].getKind() == TemplateArgument::Integral && - "Expected matrix to be matrix"); - - underlying = params[0].getAsType(); - columns = params[1].getAsIntegral().getSExtValue(); - rows = params[2].getAsIntegral().getSExtValue(); - - bool isRowMajor = DefaultRowMaj; - - HasHLSLMatOrientation(Original, &isRowMajor); - - if (!isRowMajor) - std::swap(rows, columns); - - cls = isRowMajor ? D3D_SVC_MATRIX_ROWS : D3D_SVC_MATRIX_COLUMNS; - standardType = true; - } - - break; - } - - // TODO: - // D3D_SVT_TEXTURE = 5, - // D3D_SVT_TEXTURE1D = 6, - // D3D_SVT_TEXTURE2D = 7, - // D3D_SVT_TEXTURE3D = 8, - // D3D_SVT_TEXTURECUBE = 9, - // D3D_SVT_SAMPLER = 10, - // D3D_SVT_SAMPLER1D = 11, - // D3D_SVT_SAMPLER2D = 12, - // D3D_SVT_SAMPLER3D = 13, - // D3D_SVT_SAMPLERCUBE = 14, - // D3D_SVT_BUFFER = 25, - // D3D_SVT_CBUFFER = 26, - // D3D_SVT_TBUFFER = 27, - // D3D_SVT_TEXTURE1DARRAY = 28, - // D3D_SVT_TEXTURE2DARRAY = 29, - // D3D_SVT_TEXTURE2DMS = 32, - // D3D_SVT_TEXTURE2DMSARRAY = 33, - // D3D_SVT_TEXTURECUBEARRAY = 34, - // D3D_SVT_RWTEXTURE1D = 40, - // D3D_SVT_RWTEXTURE1DARRAY = 41, - // D3D_SVT_RWTEXTURE2D = 42, - // D3D_SVT_RWTEXTURE2DARRAY = 43, - // D3D_SVT_RWTEXTURE3D = 44, - // D3D_SVT_RWBUFFER = 45, - // D3D_SVT_BYTEADDRESS_BUFFER = 46, - // D3D_SVT_RWBYTEADDRESS_BUFFER = 47, - // D3D_SVT_STRUCTURED_BUFFER = 48, - // D3D_SVT_RWSTRUCTURED_BUFFER = 49, - // D3D_SVT_APPEND_STRUCTURED_BUFFER = 50, - // D3D_SVT_CONSUME_STRUCTURED_BUFFER = 51, - } - - // Fill members - - if (!standardType && recordDecl->isCompleteDefinition()) { - - //Base types - - if (CXXRecordDecl *cxxRecordDecl = dyn_cast(recordDecl)) - if (cxxRecordDecl->getNumBases()) { - for (auto &I : cxxRecordDecl->bases()) { - - QualType qualType = I.getType(); - CXXRecordDecl *BaseDecl = - cast(qualType->castAs()->getDecl()); - - if (BaseDecl->isInterface()) - continue; - - assert(baseType == uint32_t(-1) && - "Multiple base types isn't supported in HLSL"); - - baseType = GenerateTypeInfo(ASTCtx, Refl, qualType, DefaultRowMaj); - } - } - - //Inner types - - for (Decl *decl : recordDecl->decls()) { - - // TODO: We could query other types VarDecl - - FieldDecl *fieldDecl = dyn_cast(decl); - - if (!fieldDecl) - continue; - - QualType original = fieldDecl->getType(); - std::string name = fieldDecl->getName(); - - uint32_t nameId = hasSymbols ? RegisterString(Refl, name, false) : uint32_t(-1); - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); - - if (!membersCount) - membersOffset = (uint32_t) Refl.MemberTypeIds.size(); - - assert(Refl.MemberTypeIds.size() <= (uint32_t)-1 && - "Members out of bounds"); - - Refl.MemberTypeIds.push_back(typeId); - - if (hasSymbols) - Refl.MemberNameIds.push_back(nameId); - - ++membersCount; - } - } - } - - //Type name - - D3D_SHADER_VARIABLE_TYPE type = D3D_SVT_VOID; - - if (const BuiltinType *bt = dyn_cast(underlying)) { - - if (!rows) - rows = columns = 1; - - if (cls == D3D_SVC_STRUCT) - cls = D3D_SVC_SCALAR; - - switch (bt->getKind()) { - - case BuiltinType::Void: - type = D3D_SVT_VOID; - break; - - case BuiltinType::Min10Float: - type = D3D_SVT_MIN10FLOAT; - break; - - case BuiltinType::Min16Float: - type = D3D_SVT_MIN16FLOAT; - break; - - case BuiltinType::HalfFloat: - case BuiltinType::Half: - type = D3D_SVT_FLOAT16; - break; - - case BuiltinType::Short: - type = D3D_SVT_INT16; - break; - - case BuiltinType::Min12Int: - type = D3D_SVT_MIN12INT; - break; - - case BuiltinType::Min16Int: - type = D3D_SVT_MIN16INT; - break; - - case BuiltinType::Min16UInt: - type = D3D_SVT_MIN16UINT; - break; - - case BuiltinType::UShort: - type = D3D_SVT_UINT16; - break; - - case BuiltinType::Float: - type = D3D_SVT_FLOAT; - break; - - case BuiltinType::Int: - type = D3D_SVT_INT; - break; - - case BuiltinType::UInt: - type = D3D_SVT_UINT; - break; - - case BuiltinType::Bool: - type = D3D_SVT_BOOL; - break; - - case BuiltinType::Double: - type = D3D_SVT_DOUBLE; - break; - - case BuiltinType::ULongLong: - type = D3D_SVT_UINT64; - break; - - case BuiltinType::LongLong: - type = D3D_SVT_INT64; - break; - - default: - assert(false && "Invalid builtin type"); - break; - } - } - - //Insert - - assert(Refl.Types.size() < (uint32_t)-1 && "Type id out of bounds"); - - DxcHLSLType hlslType(baseType, elementsOrArrayId, cls, type, rows, - columns, membersCount, membersOffset); - - uint32_t i = 0, j = (uint32_t)Refl.Types.size(); - - for (; i < j; ++i) - if (Refl.Types[i] == hlslType) - break; - - if (i == j) { - - if (hasSymbols) - Refl.TypeNameIds.push_back(nameId); - - Refl.Types.push_back(hlslType); - } - - return i; -} - -D3D_CBUFFER_TYPE GetBufferType(uint8_t Type) { - - switch (Type) { - - case D3D_SIT_CBUFFER: - return D3D_CT_CBUFFER; - - case D3D_SIT_TBUFFER: - return D3D_CT_TBUFFER; - - case D3D_SIT_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED: - case D3D_SIT_UAV_APPEND_STRUCTURED: - case D3D_SIT_UAV_CONSUME_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: - return D3D_CT_RESOURCE_BIND_INFO; - - default: - return D3D_CT_INTERFACE_POINTERS; - } -} - -static void FillReflectionRegisterAt( - const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, - DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, - ValueDecl *ValDesc, const std::vector &ArraySize, - DxcReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId, - bool DefaultRowMaj) { - - ArrayRef UA = ValDesc->getUnusualAnnotations(); - - hlsl::RegisterAssignment *reg = nullptr; - - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { - - if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) - continue; - - reg = cast(*It); - } - - assert(reg && "Found a register missing a RegisterAssignment, even though " - "GenerateConsistentBindings should have already generated it"); - - DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); - - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, - DxcHLSLNodeType::Register, ParentNodeId, (uint32_t)Refl.Registers.size()); - - uint32_t arrayId = PushArray(Refl, ArraySizeFlat, ArraySize); - - uint32_t bufferId = 0; - D3D_CBUFFER_TYPE bufferType = GetBufferType(inputType.RegisterType); - - if(bufferType != D3D_CT_INTERFACE_POINTERS) { - bufferId = (uint32_t) Refl.Buffers.size(); - Refl.Buffers.push_back({bufferType, nodeId}); - } - - DxcHLSLRegister regD3D12 = { - - inputType.RegisterType, - reg->RegisterNumber, - ArraySizeFlat, - (uint32_t)inputType.RegisterFlags, - inputType.TextureValue, - inputType.TextureDimension, - inputType.SampleCount, - reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() - : AutoBindingSpace, - nodeId, - arrayId, - bufferId - }; - - Refl.Registers.push_back(regD3D12); - - bool isListType = true; - - switch (inputType.RegisterType) { - - case D3D_SIT_CBUFFER: - case D3D_SIT_TBUFFER: - isListType = false; - [[fallthrough]]; - - case D3D_SIT_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED: - case D3D_SIT_UAV_APPEND_STRUCTURED: - case D3D_SIT_UAV_CONSUME_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: { - - const RecordType *recordType = Type->getAs(); - - assert(recordType && "Invalid type (not RecordType)"); - - const ClassTemplateSpecializationDecl *templateDesc = - dyn_cast(recordType->getDecl()); - - assert(templateDesc && "Invalid template type"); - - const ArrayRef ¶ms = - templateDesc->getTemplateArgs().asArray(); - - assert(params.size() == 1 && "Expected Type"); - - QualType innerType = params[0].getAsType(); - - // The name of the inner struct is $Element if 'array', otherwise equal to - // register name - - uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, innerType, DefaultRowMaj); - - SourceRange sourceRange = ValDesc->getSourceRange(); - - uint32_t nestNodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), - isListType ? "$Element" : ValDesc->getName(), nullptr, - DxcHLSLNodeType::Variable, nodeId, typeId, &sourceRange); - - break; - } - } -} - -class PrintfStream : public llvm::raw_ostream { -public: - PrintfStream() { SetUnbuffered(); } - -private: - void write_impl(const char *Ptr, size_t Size) override { - printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly - } - - uint64_t current_pos() const override { return 0; } -}; - -template -void RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, - DxcReflectionData &Refl, const T& Decls, - bool DefaultRowMaj, uint32_t ParentId) { - - for (Decl *decl : Decls) { - - ValueDecl *valDecl = dyn_cast(decl); - assert(valDecl && "Decl was expected to be a ValueDecl but wasn't"); - QualType original = valDecl->getType(); - - std::string name = valDecl->getName(); - - uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); - - uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, decl, - DxcHLSLNodeType::Variable, ParentId, typeId); - - //Handle struct recursion - - if (RecordDecl *recordDecl = dyn_cast(decl)) { - - if (!recordDecl->isCompleteDefinition()) - continue; - - RecurseBuffer(ASTCtx, SM, Refl, recordDecl->fields(), DefaultRowMaj, nodeId); - } - } -} - -uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcReflectionData &Refl, - const SourceManager &SM, DeclContext *Buffer, - uint32_t NodeId, D3D_CBUFFER_TYPE Type, - bool DefaultRowMaj) { - - assert(Refl.Buffers.size() < (uint32_t)-1 && "Buffer id out of bounds"); - uint32_t bufferId = (uint32_t)Refl.Buffers.size(); - - RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), DefaultRowMaj, NodeId); - - Refl.Buffers.push_back({Type, NodeId}); - - return bufferId; -} - -/* -static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, - DxcReflectionData &Refl, const SourceManager &SM, - uint32_t ParentNodeId) { - - PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); - - QualType desugared = Type.getDesugaredType(ASTCtx); - - PrintfStream str; - desugared.print(str, printingPolicy); - - if (Decl) - Decl->print(str); - - //Generate parameter - - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), - Decl && dyn_cast(Decl) ? dyn_cast(Decl)->getName() - : "", - Decl, DxcHLSLNodeType::Parameter, ParentNodeId, - (uint32_t)Refl.Parameters.size()); - - std::string semanticName; - - if (NamedDecl *ValDesc = dyn_cast(Decl)) { - - ArrayRef UA = ValDesc->getUnusualAnnotations(); - - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { - - if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_SemanticDecl) - continue; - - semanticName = cast(*It)->SemanticName; - } - } - - DxcHLSLParameter parameter{std::move(semanticName)}; - - type, clss, rows, columns, interpolationMode, flags; - parameter.NodeId = nodeId; - - Refl.Parameters.push_back(parameter); - - //It's a struct, add parameters recursively -}*/ - -D3D12_HLSL_REFLECTION_FEATURE &operator|=(D3D12_HLSL_REFLECTION_FEATURE &a, - D3D12_HLSL_REFLECTION_FEATURE b) { - return a = (D3D12_HLSL_REFLECTION_FEATURE)((uint32_t)a | (uint32_t)b); -} - -D3D12_HLSL_REFLECTION_FEATURE &operator&=(D3D12_HLSL_REFLECTION_FEATURE &a, - D3D12_HLSL_REFLECTION_FEATURE b) { - return a = (D3D12_HLSL_REFLECTION_FEATURE)((uint32_t)a & (uint32_t)b); -} - -D3D12_HLSL_REFLECTION_FEATURE operator~(D3D12_HLSL_REFLECTION_FEATURE a) { - return (D3D12_HLSL_REFLECTION_FEATURE)~(uint32_t)a; -} - -static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, - DiagnosticsEngine &Diags, - const SourceManager &SM, - DxcReflectionData &Refl, - uint32_t AutoBindingSpace, - uint32_t Depth, - D3D12_HLSL_REFLECTION_FEATURE Features, - uint32_t ParentNodeId, bool DefaultRowMaj) { - - PrintfStream pfStream; - - PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); - - printingPolicy.SuppressInitializers = true; - printingPolicy.AnonymousTagLocations = false; - printingPolicy.TerseOutput = - true; // No inheritance list, trailing semicolons, etc. - printingPolicy.PolishForDeclaration = true; // Makes it print as a decl - printingPolicy.SuppressSpecifiers = false; // Prints e.g. "static" or "inline" - printingPolicy.SuppressScope = true; - - // Traverse AST to grab reflection data - - //TODO: Niels, scopes (if/switch/for/empty scope) - - for (Decl *it : Ctx.decls()) { - - SourceLocation Loc = it->getLocation(); - if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) - continue; - - if (HLSLBufferDecl *CBuffer = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) - continue; - - // TODO: Add for reflection even though it might not be important - - if (Depth != 0) - continue; - - hlsl::RegisterAssignment *reg = nullptr; - ArrayRef UA = CBuffer->getUnusualAnnotations(); - - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { - - if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) - continue; - - reg = cast(*It); - } - - assert(reg && - "Found a cbuffer missing a RegisterAssignment, even though " - "GenerateConsistentBindings should have already generated it"); - - uint32_t nodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), CBuffer->getName(), - CBuffer, DxcHLSLNodeType::Register, ParentNodeId, - (uint32_t)Refl.Registers.size()); - - uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, SM, CBuffer, nodeId, - D3D_CT_CBUFFER, DefaultRowMaj); - - DxcHLSLRegister regD3D12 = { - - D3D_SIT_CBUFFER, - reg->RegisterNumber, - 1, - (uint32_t) D3D_SIF_USERPACKED, - (D3D_RESOURCE_RETURN_TYPE) 0, - D3D_SRV_DIMENSION_UNKNOWN, - 0, - reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() - : AutoBindingSpace, - nodeId, - (uint32_t)-1, - bufferId - }; - - Refl.Registers.push_back(regD3D12); - } - - else if (FunctionDecl *Func = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS)) - continue; - - const FunctionDecl *Definition = nullptr; - - uint32_t nodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), Func->getName(), Func, - DxcHLSLNodeType::Function, ParentNodeId, - (uint32_t)Refl.Functions.size()); - - bool hasDefinition = Func->hasBody(Definition); - DxcHLSLFunction func = {nodeId, Func->getNumParams(), - !Func->getReturnType().getTypePtr()->isVoidType(), - hasDefinition}; - - /* - for (uint32_t i = 0; i < func.NumParameters; ++i) - AddFunctionParameters(ASTCtx, Func->getParamDecl(i)->getType(), - Func->getParamDecl(i), Refl, SM, nodeId); - - if (func.HasReturn) - AddFunctionParameters(ASTCtx, Func->getReturnType(), nullptr, Refl, SM, - nodeId);*/ - - Refl.Functions.push_back(std::move(func)); - - if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { - RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, - nodeId, DefaultRowMaj); - } - } - - else if (FieldDecl *Field = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - //Field->print(pfStream, printingPolicy); - } - - else if (TypedefDecl *Typedef = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - // Typedef->print(pfStream, printingPolicy); - } - - else if (TypeAliasDecl *TypeAlias = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - // TypeAlias->print(pfStream, printingPolicy); - } - - else if (EnumDecl *Enum = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), Enum->getName(), Enum, - DxcHLSLNodeType::Enum, ParentNodeId, (uint32_t)Refl.Enums.size()); - - for (EnumConstantDecl *EnumValue : Enum->enumerators()) { - - uint32_t childNodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), EnumValue->getName(), - EnumValue, DxcHLSLNodeType::EnumValue, nodeId, - (uint32_t)Refl.EnumValues.size()); - - Refl.EnumValues.push_back( - {EnumValue->getInitVal().getSExtValue(), childNodeId}); - } - - assert(Refl.EnumValues.size() < (uint32_t)(1 << 30) && - "Enum values overflow"); - - QualType enumType = Enum->getIntegerType(); - QualType desugared = enumType.getDesugaredType(ASTCtx); - const auto &semantics = ASTCtx.getTypeInfo(desugared); - - D3D12_HLSL_ENUM_TYPE type; - - switch (semantics.Width) { - - default: - case 32: - type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT - : D3D12_HLSL_ENUM_TYPE_INT; - break; - - case 16: - type = desugared->isUnsignedIntegerType() - ? D3D12_HLSL_ENUM_TYPE_UINT16_T - : D3D12_HLSL_ENUM_TYPE_INT16_T; - break; - - case 64: - type = desugared->isUnsignedIntegerType() - ? D3D12_HLSL_ENUM_TYPE_UINT64_T - : D3D12_HLSL_ENUM_TYPE_INT64_T; - break; - } - - Refl.Enums.push_back({nodeId, type}); - } - - else if (ValueDecl *ValDecl = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) - continue; - - //TODO: Handle values - - //ValDecl->print(pfStream); - - uint32_t arraySize = 1; - QualType type = ValDecl->getType(); - std::vector arrayElem; - - while (const ConstantArrayType *arr = - dyn_cast(type)) { - uint32_t current = arr->getSize().getZExtValue(); - arrayElem.push_back(current); - arraySize *= arr->getSize().getZExtValue(); - type = arr->getElementType(); - } - - if (!IsHLSLResourceType(type)) - continue; - - // TODO: Add for reflection even though it might not be important - - if (Depth != 0) - continue; - - FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, ValDecl, - arrayElem, Refl, AutoBindingSpace, ParentNodeId, - DefaultRowMaj); - } - - else if (RecordDecl *RecDecl = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - //RecDecl->print(pfStream, printingPolicy); - /*RecursiveReflectHLSL(*RecDecl, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, InclusionFlags, nodeId);*/ - } - - else if (NamespaceDecl *Namespace = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES)) - continue; - - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), Namespace->getName(), Namespace, - DxcHLSLNodeType::Namespace, ParentNodeId, 0); - - RecursiveReflectHLSL(*Namespace, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, nodeId, - DefaultRowMaj); - } - } -} - -static void ReflectHLSL(ASTHelper &astHelper, DxcReflectionData& Refl, - uint32_t AutoBindingSpace, - D3D12_HLSL_REFLECTION_FEATURE Features, - bool DefaultRowMaj) { - - TranslationUnitDecl &Ctx = *astHelper.tu; - DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); - const SourceManager &SM = astHelper.compiler.getSourceManager(); - - Refl = {}; - Refl.Features = Features; - - if (Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { - Refl.Strings.push_back(""); - Refl.StringsToId[""] = 0; - Refl.NodeSymbols.push_back(DxcHLSLNodeSymbol(0, 0, 0, 0, 0, 0)); - } - - Refl.Nodes.push_back( - DxcHLSLNode{DxcHLSLNodeType::Namespace, 0, 0, 0, 0xFFFF, 0}); - - RecursiveReflectHLSL(Ctx, astHelper.compiler.getASTContext(), Diags, SM, Refl, - AutoBindingSpace, 0, Features, 0, DefaultRowMaj); -} - -static void GlobalVariableAsExternByDefault(DeclContext &Ctx) { - for (auto it = Ctx.decls_begin(); it != Ctx.decls_end();) { - auto cur = it++; - if (VarDecl *VD = dyn_cast(*cur)) { - bool isInternal = - VD->getStorageClass() == SC_Static || VD->isInAnonymousNamespace(); - if (!isInternal) { - VD->setStorageClass(StorageClass::SC_Extern); - } - } - // Only iterate on namespaces. - if (NamespaceDecl *DC = dyn_cast(*cur)) { - GlobalVariableAsExternByDefault(*DC); - } - } -} - -char RegisterGetSpaceChar(const DxcHLSLRegister ®) { - - switch (reg.Type) { - - case D3D_SIT_UAV_RWTYPED: - case D3D_SIT_UAV_RWSTRUCTURED: - case D3D_SIT_UAV_RWBYTEADDRESS: - case D3D_SIT_UAV_APPEND_STRUCTURED: - case D3D_SIT_UAV_CONSUME_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: - case D3D_SIT_UAV_FEEDBACKTEXTURE: - return 'u'; - - case D3D_SIT_CBUFFER: - return 'b'; - - case D3D_SIT_SAMPLER: - return 's'; - - default: - return 't'; - } -} - -std::string RegisterGetArraySize(const DxcReflectionData &Refl, const DxcHLSLRegister ®) { - - if (reg.ArrayId != (uint32_t)-1) { - - DxcHLSLArray arr = Refl.Arrays[reg.ArrayId]; - std::string str; - - for (uint32_t i = 0; i < arr.ArrayElem(); ++i) - str += "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart() + i]) + "]"; - - return str; - } - - return reg.BindCount > 1 ? "[" + std::to_string(reg.BindCount) + "]" : ""; -} - -std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { - - static const char *arr[] = { - "uint", "int", "uint64_t", "int64_t", "uint16_t", "int16_t", - }; - - return arr[type]; -} - -std::string NodeTypeToString(DxcHLSLNodeType type) { - - static const char *arr[] = {"Register", "Function", "Enum", "EnumValue", - "Namespace", "Typedef", "Using", "Variable", - "Parameter", "Type"}; - - return arr[(int)type]; -} - -std::string GetBuiltinTypeName(const DxcReflectionData &Refl, - const DxcHLSLType &Type) { - - std::string type; - - if (Type.Class != D3D_SVC_STRUCT) { - - static const char *arr[] = {"void", - "bool", - "int", - "float", - "string", - NULL, - "Texture1D", - "Texture2D", - "Texture3D", - "TextureCube", - "SamplerState", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "uint", - "uint8_t", - NULL, - NULL, - NULL, - NULL, - "Buffer", - "ConstantBuffer", - NULL, - "Texture1DArray", - "Texture2DArray", - NULL, - NULL, - "Texture2DMS", - "Texture2DMSArray", - "TextureCubeArray", - NULL, - NULL, - NULL, - NULL, - "double", - "RWTexture1D", - "RWTexture1DArray", - "RWTexture2D", - "RWTexture2DArray", - "RWTexture3D", - "RWBuffer", - "ByteAddressBuffer", - "RWByteAddressBuffer", - "StructuredBuffer", - "RWStructuredBuffer", - "AppendStructuredBuffer", - "ConsumeStructuredBuffer", - "min8float", - "min10float", - "min16float", - "min12int", - "min16int", - "min16uint", - "int16_t", - "uint16_t", - "float16_t", - "int64_t", - "uint64_t"}; - - const char *ptr = arr[Type.Type]; - - if (ptr) - type = ptr; - } - - switch (Type.Class) { - - case D3D_SVC_MATRIX_ROWS: - case D3D_SVC_VECTOR: - - type += std::to_string(Type.Columns); - - if (Type.Class == D3D_SVC_MATRIX_ROWS) - type += "x" + std::to_string(Type.Rows); - - break; - - case D3D_SVC_MATRIX_COLUMNS: - type += std::to_string(Type.Rows) + "x" + std::to_string(Type.Columns); - break; - } - - return type; -} - -std::string PrintTypeInfo(const DxcReflectionData &Refl, - const DxcHLSLType &Type, - const std::string &PreviousTypeName) { - - std::string result; - - if (Type.IsMultiDimensionalArray()) { - - const DxcHLSLArray &arr = Refl.Arrays[Type.GetMultiDimensionalArrayId()]; - - for (uint32_t i = 0; i < arr.ArrayElem(); ++i) - result += - "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart() + i]) + "]"; - - } - - else if (Type.IsArray()) - result += "[" + std::to_string(Type.Get1DElements()) + "]"; - - // Obtain type name (returns empty if it's not a builtin type) - - std::string underlyingTypeName = GetBuiltinTypeName(Refl, Type); - - if (PreviousTypeName != underlyingTypeName && underlyingTypeName.size()) - result += " (" + underlyingTypeName + ")"; - - return result; -} - -void RecursePrintType(const DxcReflectionData &Refl, uint32_t TypeId, - uint32_t Depth, const char *Prefix = "") { - - const DxcHLSLType &type = Refl.Types[TypeId]; - - bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - std::string name = hasSymbols ? Refl.Strings[Refl.TypeNameIds[TypeId]] - : GetBuiltinTypeName(Refl, type); - - if (name.empty() && !hasSymbols) - name = "(unknown)"; - - printf("%s%s%s%s\n", std::string(Depth, '\t').c_str(), Prefix, name.c_str(), - PrintTypeInfo(Refl, type, name).c_str()); - - if (type.BaseClass != uint32_t(-1)) - RecursePrintType(Refl, type.BaseClass, Depth + 1, Prefix); - - for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { - - uint32_t memberId = type.GetMemberStart() + i; - std::string prefix = - (hasSymbols ? Refl.Strings[Refl.MemberNameIds[memberId]] : "(unknown)") + ": "; - - RecursePrintType(Refl, Refl.MemberTypeIds[memberId], Depth + 1, prefix.c_str()); - } -} - -uint32_t RecursePrint(const DxcReflectionData &Refl, uint32_t NodeId, - uint32_t Depth, uint32_t IndexInParent) { - - const DxcHLSLNode &node = Refl.Nodes[NodeId]; - - uint32_t typeToPrint = (uint32_t)-1; - - if (NodeId) { - - bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - printf("%s%s %s\n", std::string(Depth - 1, '\t').c_str(), - NodeTypeToString(node.GetNodeType()).c_str(), - hasSymbols ? Refl.Strings[Refl.NodeSymbols[NodeId].NameId].c_str() - : "(unknown)"); - - for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) { - - const DxcHLSLAnnotation &annotation = - Refl.Annotations[node.GetAnnotationStart() + i]; - - printf(annotation.GetIsBuiltin() ? "%s[%s]\n" : "%s[[%s]]\n", - std::string(Depth, '\t').c_str(), - Refl.StringsNonDebug[annotation.GetStringNonDebug()] - .c_str()); - } - - uint32_t localId = node.GetLocalId(); - - switch (node.GetNodeType()) { - - case DxcHLSLNodeType::Register: { - const DxcHLSLRegister ® = Refl.Registers[localId]; - printf("%s%s : register(%c%u, space%u);\n", - std::string(Depth, '\t').c_str(), - RegisterGetArraySize(Refl, reg).c_str(), RegisterGetSpaceChar(reg), - reg.BindPoint, reg.Space); - break; - } - - case DxcHLSLNodeType::Variable: - typeToPrint = localId; - break; - - case DxcHLSLNodeType::Function: { - const DxcHLSLFunction &func = Refl.Functions[localId]; - printf("%sreturn: %s, hasDefinition: %s, numParams: %u\n", - std::string(Depth, '\t').c_str(), - func.HasReturn() ? "true" : "false", - func.HasDefinition() ? "true" : "false", func.GetNumParameters()); - - break; - } - - case DxcHLSLNodeType::Enum: - printf("%s: %s\n", std::string(Depth, '\t').c_str(), - EnumTypeToString(Refl.Enums[localId].Type).c_str()); - break; - - case DxcHLSLNodeType::EnumValue: { - printf("%s#%u = %" PRIi64 "\n", std::string(Depth, '\t').c_str(), - IndexInParent, Refl.EnumValues[localId].Value); - break; - } - - //TODO: - case DxcHLSLNodeType::Type: - case DxcHLSLNodeType::Typedef: - case DxcHLSLNodeType::Using: - case DxcHLSLNodeType::Parameter: - break; - - case DxcHLSLNodeType::Namespace: - default: - break; - } - } - - if (typeToPrint != (uint32_t)-1) - RecursePrintType(Refl, typeToPrint, Depth); - - for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) - i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1, j); - - return node.GetChildCount(); -} - -struct DxcHLSLHeader { - - uint32_t MagicNumber; - uint16_t Version; - uint16_t Sources; - - D3D12_HLSL_REFLECTION_FEATURE Features; - uint32_t StringsNonDebug; - - uint32_t Strings; - uint32_t Nodes; - - uint32_t Registers; - uint32_t Functions; - - uint32_t Enums; - uint32_t EnumValues; - - uint32_t Annotations; - uint32_t Arrays; - - uint32_t ArraySizes; - uint32_t Members; - - uint32_t Types; - uint32_t Buffers; -}; - -template -T &UnsafeCast(std::vector &Bytes, uint64_t Offset) { - return *(T *)(Bytes.data() + Offset); -} - -template -const T &UnsafeCast(const std::vector &Bytes, uint64_t Offset) { - return *(const T *)(Bytes.data() + Offset); -} - -template -void SkipPadding(uint64_t& Offset) { - Offset = (Offset + alignof(T) - 1) / alignof(T) * alignof(T); -} - -template -void Skip(uint64_t& Offset, const std::vector& Vec) { - Offset += Vec.size() * sizeof(T); -} - -template -void Advance(uint64_t& Offset, const std::vector& Vec) { - SkipPadding(Offset); - Skip(Offset, Vec); -} - -template <> -void Advance(uint64_t &Offset, - const std::vector &Vec) { - for (const std::string &str : Vec) { - Offset += str.size() >= 128 ? 2 : 1; - Offset += str.size(); - } -} - -template -void Advance(uint64_t& Offset, const std::vector& Vec, const std::vector& Vec2, args... arg) { - Advance(Offset, Vec); - Advance(Offset, Vec2, arg...); -} - -template -void Append(std::vector &Bytes, uint64_t &Offset, - const std::vector &Vec) { - static_assert(std::is_pod_v, "Append only works on POD types"); - SkipPadding(Offset); - std::memcpy(&UnsafeCast(Bytes, Offset), Vec.data(), - Vec.size() * sizeof(T)); - Skip(Offset, Vec); -} - -template <> -void Append(std::vector &Bytes, uint64_t &Offset, - const std::vector &Vec) { - - for (const std::string &str : Vec) { - - if (str.size() >= 128) { - UnsafeCast(Bytes, Offset++) = - (uint8_t)(str.size() & 0x7F) | 0x80; - UnsafeCast(Bytes, Offset++) = (uint8_t)(str.size() >> 7); - } - - else - UnsafeCast(Bytes, Offset++) = (uint8_t)str.size(); - - std::memcpy(&UnsafeCast(Bytes, Offset), str.data(), str.size()); - Offset += str.size(); - } -} - -template -void Append(std::vector &Bytes, uint64_t &Offset, - const std::vector &Vec, const std::vector &Vec2, - args... arg) { - Append(Bytes, Offset, Vec); - Append(Bytes, Offset, Vec2, arg...); -} - -template >> -void Consume(const std::vector &Bytes, uint64_t &Offset, T &t) { - - static_assert(std::is_pod_v, "Consume only works on POD types"); - - SkipPadding(Offset); - - if (Offset + sizeof(T) > Bytes.size()) - throw std::out_of_range("Couldn't consume; out of bounds!"); - - std::memcpy(&t, &UnsafeCast(Bytes, Offset), sizeof(T)); - Offset += sizeof(T); -} - -template -void Consume(const std::vector &Bytes, uint64_t &Offset, T *target, - uint64_t Len) { - - static_assert(std::is_pod_v, "Consume only works on POD types"); - - SkipPadding(Offset); - - if (Offset + sizeof(T) * Len > Bytes.size()) - throw std::out_of_range("Couldn't consume; out of bounds!"); - - std::memcpy(target, &UnsafeCast(Bytes, Offset), sizeof(T) * Len); - Offset += sizeof(T) * Len; -} - -template -void Consume(const std::vector &Bytes, uint64_t &Offset, - std::vector &Vec, uint64_t Len) { - Vec.resize(Len); - Consume(Bytes, Offset, Vec.data(), Len); -} - -template <> -void Consume(const std::vector &Bytes, uint64_t &Offset, - std::vector &Vec, uint64_t Len) { - Vec.resize(Len); - - for (uint64_t i = 0; i < Len; ++i) { - - if (Offset >= Bytes.size()) - throw std::out_of_range("Couldn't consume string len; out of bounds!"); - - uint16_t ourLen = uint8_t(Bytes.at(Offset++)); - - if (ourLen >> 7) { - - if (Offset >= Bytes.size()) - throw std::out_of_range("Couldn't consume string len; out of bounds!"); - - ourLen &= ~(1 << 7); - ourLen |= uint16_t(Bytes.at(Offset++)) << 7; - } - - if (Offset + ourLen > Bytes.size()) - throw std::out_of_range("Couldn't consume string len; out of bounds!"); - - Vec[i].resize(ourLen); - std::memcpy(Vec[i].data(), Bytes.data() + Offset, ourLen); - Offset += ourLen; - } -} - -template -void Consume(const std::vector &Bytes, uint64_t &Offset, - std::vector &Vec, uint64_t Len, std::vector &Vec2, - uint64_t Len2, args&... arg) { - Consume(Bytes, Offset, Vec, Len); - Consume(Bytes, Offset, Vec2, Len2, arg...); -} - -static constexpr uint32_t DxcReflectionDataMagic = DXC_FOURCC('D', 'H', 'R', 'D'); -static constexpr uint16_t DxcReflectionDataVersion = 0; - -void DxcReflectionData::StripSymbols() { - Strings.clear(); - StringsToId.clear(); - Sources.clear(); - StringToSourceId.clear(); - FullyResolvedToNodeId.clear(); - NodeIdToFullyResolved.clear(); - FullyResolvedToMemberId.clear(); - NodeSymbols.clear(); - TypeNameIds.clear(); - MemberNameIds.clear(); - Features &= ~D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; -} - -void RecurseNameGenerationType(DxcReflectionData &Refl, uint32_t TypeId, - uint32_t LocalId, const std::string &Parent) { - - const DxcHLSLType &type = Refl.Types[TypeId]; - - if (type.Class == D3D_SVC_STRUCT) - for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { - - uint32_t memberId = i + type.GetMemberStart(); - std::string memberName = - Parent + "." + Refl.Strings[Refl.MemberNameIds[memberId]]; - - Refl.FullyResolvedToMemberId[memberName] = memberId; - - RecurseNameGenerationType(Refl, Refl.MemberTypeIds[memberId], i, - memberName); +static void GlobalVariableAsExternByDefault(DeclContext &Ctx) { + for (auto it = Ctx.decls_begin(); it != Ctx.decls_end();) { + auto cur = it++; + if (VarDecl *VD = dyn_cast(*cur)) { + bool isInternal = + VD->getStorageClass() == SC_Static || VD->isInAnonymousNamespace(); + if (!isInternal) { + VD->setStorageClass(StorageClass::SC_Extern); } -} - -uint32_t RecurseNameGeneration(DxcReflectionData &Refl, uint32_t NodeId, - uint32_t LocalId, const std::string &Parent, - bool IsDot) { - - const DxcHLSLNode &node = Refl.Nodes[NodeId]; - std::string self = Refl.Strings[Refl.NodeSymbols[NodeId].NameId]; - - if (self.empty() && NodeId) - self = std::to_string(LocalId); - - self = Parent.empty() ? self : Parent + (IsDot ? "." : "::") + self; - Refl.FullyResolvedToNodeId[self] = NodeId; - Refl.NodeIdToFullyResolved[NodeId] = self; - - bool isDotChild = node.GetNodeType() == DxcHLSLNodeType::Register; - bool isVar = node.GetNodeType() == DxcHLSLNodeType::Variable; - - for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) - i += RecurseNameGeneration(Refl, NodeId + 1 + i, j, self, isDotChild); - - if (isVar) { - - uint32_t typeId = node.GetLocalId(); - const DxcHLSLType &type = Refl.Types[typeId]; - - if (type.Class == D3D_SVC_STRUCT) - for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { - - uint32_t memberId = i + type.GetMemberStart(); - std::string memberName = - self + "." + Refl.Strings[Refl.MemberNameIds[memberId]]; - - Refl.FullyResolvedToMemberId[memberName] = memberId; - - RecurseNameGenerationType(Refl, Refl.MemberTypeIds[memberId], i, - memberName); - } - } - - return node.GetChildCount(); -} - -bool DxcReflectionData::GenerateNameLookupTable() { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) || Nodes.empty()) - return false; - - NodeIdToFullyResolved.resize(Nodes.size()); - RecurseNameGeneration(*this, 0, 0, "", false); - return true; -} - -void DxcReflectionData::Dump(std::vector &Bytes) const { - - uint64_t toReserve = sizeof(DxcHLSLHeader); - - Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, - Enums, EnumValues, Annotations, ArraySizes, MemberTypeIds, MemberNameIds, Types, TypeNameIds, Buffers); - - Bytes.resize(toReserve); - - toReserve = 0; - - UnsafeCast(Bytes, toReserve) = { - DxcReflectionDataMagic, DxcReflectionDataVersion, - uint16_t(Sources.size()), Features, - uint32_t(StringsNonDebug.size()), uint32_t(Strings.size()), - uint32_t(Nodes.size()), uint32_t(Registers.size()), - uint32_t(Functions.size()), uint32_t(Enums.size()), - uint32_t(EnumValues.size()), uint32_t(Annotations.size()), - uint32_t(Arrays.size()), uint32_t(ArraySizes.size()), - uint32_t(MemberTypeIds.size()), uint32_t(Types.size()), - uint32_t(Buffers.size())}; - - toReserve += sizeof(DxcHLSLHeader); - - Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, - NodeSymbols, Registers, - Functions, Enums, EnumValues, Annotations, ArraySizes, MemberTypeIds, - MemberNameIds, Types, TypeNameIds, Buffers); -} - -DxcReflectionData::DxcReflectionData(const std::vector &Bytes, - bool MakeNameLookupTable) { - - uint64_t off = 0; - DxcHLSLHeader header; - Consume(Bytes, off, header); - - if (header.MagicNumber != DxcReflectionDataMagic) - throw std::invalid_argument("Invalid magic number"); - - if (header.Version != DxcReflectionDataVersion) - throw std::invalid_argument("Unrecognized version number"); - - Features = header.Features; - - bool hasSymbolInfo = Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - if (!hasSymbolInfo && (header.Sources || header.Strings)) - throw std::invalid_argument("Sources are invalid without symbols"); - - uint32_t nodeSymbolCount = hasSymbolInfo ? header.Nodes : 0; - uint32_t memberSymbolCount = hasSymbolInfo ? header.Members : 0; - uint32_t typeSymbolCount = hasSymbolInfo ? header.Types : 0; - - Consume(Bytes, off, Strings, header.Strings, StringsNonDebug, - header.StringsNonDebug, Sources, header.Sources, Nodes, header.Nodes, - NodeSymbols, nodeSymbolCount, Registers, header.Registers, Functions, - header.Functions, Enums, header.Enums, EnumValues, header.EnumValues, - Annotations, header.Annotations, ArraySizes, header.ArraySizes, - MemberTypeIds, header.Members, MemberNameIds, memberSymbolCount, - Types, header.Types, TypeNameIds, typeSymbolCount, Buffers, - header.Buffers); - - if (off != Bytes.size()) - throw std::invalid_argument("Reflection info had unrecognized data on the back"); - - //Validation errors are throws to prevent accessing invalid data - - for(uint32_t i = 0; i < header.Sources; ++i) - if(Sources[i] >= header.Strings) - throw std::invalid_argument("Source path out of bounds"); - - for(uint32_t i = 0; i < header.Nodes; ++i) { - - const DxcHLSLNode &node = Nodes[i]; - - if (hasSymbolInfo && (NodeSymbols[i].NameId >= header.Strings || - (NodeSymbols[i].FileNameId != uint16_t(-1) && - NodeSymbols[i].FileNameId >= header.Sources))) - throw std::invalid_argument("Node " + std::to_string(i) + - " points to invalid name or file name"); - - if( - node.GetAnnotationStart() + node.GetAnnotationCount() > header.Annotations || - node.GetNodeType() > DxcHLSLNodeType::End || - (i && node.GetParentId() >= i) || - i + node.GetChildCount() > header.Nodes - ) - throw std::invalid_argument("Node " + std::to_string(i) + " is invalid"); - - uint32_t maxValue = 1; - - switch(node.GetNodeType()) { - case DxcHLSLNodeType::Register: - maxValue = header.Registers; - break; - case DxcHLSLNodeType::Function: - maxValue = header.Functions; - break; - case DxcHLSLNodeType::Enum: - maxValue = header.Enums; - break; - case DxcHLSLNodeType::EnumValue: - maxValue = header.EnumValues; - break; - case DxcHLSLNodeType::Typedef: - case DxcHLSLNodeType::Using: - case DxcHLSLNodeType::Type: - case DxcHLSLNodeType::Variable: - maxValue = header.Types; - break; - case DxcHLSLNodeType::Parameter: - throw std::invalid_argument("Node " + std::to_string(i) + " has unsupported 'parameter' type"); } - - if(node.GetLocalId() >= maxValue) - throw std::invalid_argument("Node " + std::to_string(i) + " has invalid localId"); - } - - for(uint32_t i = 0; i < header.Registers; ++i) { - - const DxcHLSLRegister ® = Registers[i]; - - if( - reg.NodeId >= header.Nodes || - Nodes[reg.NodeId].GetNodeType() != DxcHLSLNodeType::Register || - Nodes[reg.NodeId].GetLocalId() != i - ) - throw std::invalid_argument("Register " + std::to_string(i) + " points to an invalid nodeId"); - - if (reg.Type > D3D_SIT_UAV_FEEDBACKTEXTURE || - reg.ReturnType > D3D_RETURN_TYPE_CONTINUED || - reg.Dimension > D3D_SRV_DIMENSION_BUFFEREX || !reg.BindCount || - (reg.ArrayId != uint32_t(-1) && reg.ArrayId >= header.Arrays) || - (reg.ArrayId != uint32_t(-1) && reg.BindCount <= 1)) - throw std::invalid_argument( - "Register " + std::to_string(i) + - " invalid type, returnType, bindCount, array or dimension"); - - D3D_CBUFFER_TYPE bufferType = GetBufferType(reg.Type); - - if(bufferType != D3D_CT_INTERFACE_POINTERS) { - - if (reg.BufferId >= header.Buffers || - Buffers[reg.BufferId].NodeId != reg.NodeId || - Buffers[reg.BufferId].Type != bufferType) - throw std::invalid_argument("Register " + std::to_string(i) + - " invalid buffer referenced by register"); - } - } - - for(uint32_t i = 0; i < header.Functions; ++i) { - - const DxcHLSLFunction &func = Functions[i]; - - if (func.NodeId >= header.Nodes || - Nodes[func.NodeId].GetNodeType() != DxcHLSLNodeType::Function || - Nodes[func.NodeId].GetLocalId() != i) - throw std::invalid_argument("Function " + std::to_string(i) + - " points to an invalid nodeId"); - } - - for(uint32_t i = 0; i < header.Enums; ++i) { - - const DxcHLSLEnumDesc &enm = Enums[i]; - - if (enm.NodeId >= header.Nodes || - Nodes[enm.NodeId].GetNodeType() != DxcHLSLNodeType::Enum || - Nodes[enm.NodeId].GetLocalId() != i) - throw std::invalid_argument("Function " + std::to_string(i) + - " points to an invalid nodeId"); - - if (enm.Type < D3D12_HLSL_ENUM_TYPE_START || - enm.Type > D3D12_HLSL_ENUM_TYPE_END) - throw std::invalid_argument("Enum " + std::to_string(i) + - " has an invalid type"); - - const DxcHLSLNode &node = Nodes[enm.NodeId]; - - for (uint32_t j = 0; j < node.GetChildCount(); ++j) { - - const DxcHLSLNode &child = Nodes[enm.NodeId + 1 + j]; - - if (child.GetChildCount() != 0 || - child.GetNodeType() != DxcHLSLNodeType::EnumValue) - throw std::invalid_argument("Enum " + std::to_string(i) + - " has an invalid enum value"); - } - } - - for(uint32_t i = 0; i < header.EnumValues; ++i) { - - const DxcHLSLEnumValue &enumVal = EnumValues[i]; - - if (enumVal.NodeId >= header.Nodes || - Nodes[enumVal.NodeId].GetNodeType() != DxcHLSLNodeType::EnumValue || - Nodes[enumVal.NodeId].GetLocalId() != i || - Nodes[Nodes[enumVal.NodeId].GetParentId()].GetNodeType() != - DxcHLSLNodeType::Enum) - throw std::invalid_argument("Enum " + std::to_string(i) + - " points to an invalid nodeId"); - } - - for (uint32_t i = 0; i < header.Arrays; ++i) { - - const DxcHLSLArray &arr = Arrays[i]; - - if (arr.ArrayElem() <= 1 || arr.ArrayElem() > 8 || - arr.ArrayStart() + arr.ArrayElem() > header.ArraySizes) - throw std::invalid_argument("Array " + std::to_string(i) + - " points to an invalid array element"); - } - - for (uint32_t i = 0; i < header.Annotations; ++i) - if (Annotations[i].GetStringNonDebug() >= header.StringsNonDebug) - throw std::invalid_argument("Annotation " + std::to_string(i) + - " points to an invalid string"); - - for (uint32_t i = 0; i < header.Buffers; ++i) { - - const DxcHLSLBuffer &buf = Buffers[i]; - - if (buf.NodeId >= header.Nodes || - Nodes[buf.NodeId].GetNodeType() != DxcHLSLNodeType::Register || - Nodes[buf.NodeId].GetLocalId() >= header.Registers || - Registers[Nodes[buf.NodeId].GetLocalId()].BufferId != i) - throw std::invalid_argument("Buffer " + std::to_string(i) + - " points to an invalid nodeId"); - - const DxcHLSLNode &node = Nodes[buf.NodeId]; - - if (!node.GetChildCount()) - throw std::invalid_argument("Buffer " + std::to_string(i) + - " requires at least one Variable child"); - - for (uint32_t j = 0; j < node.GetChildCount(); ++j) { - - const DxcHLSLNode &child = Nodes[buf.NodeId + 1 + j]; - - if (child.GetChildCount() != 0 || - child.GetNodeType() != DxcHLSLNodeType::Variable) - throw std::invalid_argument("Buffer " + std::to_string(i) + - " has to have only Variable child nodes"); - } - } - - for (uint32_t i = 0; i < header.Members; ++i) { - - if (MemberTypeIds[i] >= header.Types) - throw std::invalid_argument("Member " + std::to_string(i) + - " points to an invalid type"); - - if (hasSymbolInfo && MemberNameIds[i] >= header.Strings) - throw std::invalid_argument("Member " + std::to_string(i) + - " points to an invalid string"); - } - - for (uint32_t i = 0; i < header.Types; ++i) { - - const DxcHLSLType &type = Types[i]; - - if (hasSymbolInfo && TypeNameIds[i] >= header.Strings) - throw std::invalid_argument("Type " + std::to_string(i) + - " points to an invalid string"); - - if ((type.BaseClass != uint32_t(-1) && type.BaseClass >= header.Types) || - type.GetMemberStart() + type.GetMemberCount() > header.Members || - (type.ElementsOrArrayId >> 31 && - (type.ElementsOrArrayId << 1 >> 1) >= header.Arrays)) - throw std::invalid_argument( - "Type " + std::to_string(i) + - " points to an invalid string, base class or member"); - - switch (type.Class) { - - case D3D_SVC_SCALAR: - - if (type.Columns != 1) - throw std::invalid_argument("Type (scalar) " + std::to_string(i) + - " should have columns == 1"); - - [[fallthrough]]; - - case D3D_SVC_VECTOR: - - if (type.Rows != 1) - throw std::invalid_argument("Type (scalar/vector) " + - std::to_string(i) + - " should have rows == 1"); - - [[fallthrough]]; - - case D3D_SVC_MATRIX_ROWS: - case D3D_SVC_MATRIX_COLUMNS: - - if (!type.Rows || !type.Columns || type.Rows > 128 || type.Columns > 128) - throw std::invalid_argument("Type (scalar/vector/matrix) " + - std::to_string(i) + - " has invalid rows or columns"); - - switch (type.Type) { - case D3D_SVT_BOOL: - case D3D_SVT_INT: - case D3D_SVT_FLOAT: - case D3D_SVT_MIN8FLOAT: - case D3D_SVT_MIN10FLOAT: - case D3D_SVT_MIN16FLOAT: - case D3D_SVT_MIN12INT: - case D3D_SVT_MIN16INT: - case D3D_SVT_MIN16UINT: - case D3D_SVT_INT16: - case D3D_SVT_UINT16: - case D3D_SVT_FLOAT16: - case D3D_SVT_INT64: - case D3D_SVT_UINT64: - case D3D_SVT_UINT: - case D3D_SVT_DOUBLE: - break; - - default: - throw std::invalid_argument("Type (scalar/matrix/vector) " + - std::to_string(i) + - " is of invalid type"); - } - - break; - - case D3D_SVC_STRUCT: - - if (!type.GetMemberCount()) - throw std::invalid_argument("Type (struct) " + std::to_string(i) + - " is missing children"); - if (type.Type) - throw std::invalid_argument("Type (struct) " + - std::to_string(i) + - " shouldn't have rows or columns"); - - if (type.Rows || type.Columns) - throw std::invalid_argument("Type (struct) " + - std::to_string(i) + - " shouldn't have rows or columns"); - - break; - - case D3D_SVC_OBJECT: - - switch (type.Type) { - - case D3D_SVT_STRING: - case D3D_SVT_TEXTURE1D: - case D3D_SVT_TEXTURE2D: - case D3D_SVT_TEXTURE3D: - case D3D_SVT_TEXTURECUBE: - case D3D_SVT_SAMPLER: - case D3D_SVT_BUFFER: - case D3D_SVT_CBUFFER: - case D3D_SVT_TBUFFER: - case D3D_SVT_TEXTURE1DARRAY: - case D3D_SVT_TEXTURE2DARRAY: - case D3D_SVT_TEXTURE2DMS: - case D3D_SVT_TEXTURE2DMSARRAY: - case D3D_SVT_TEXTURECUBEARRAY: - case D3D_SVT_RWTEXTURE1D: - case D3D_SVT_RWTEXTURE1DARRAY: - case D3D_SVT_RWTEXTURE2D: - case D3D_SVT_RWTEXTURE2DARRAY: - case D3D_SVT_RWTEXTURE3D: - case D3D_SVT_RWBUFFER: - case D3D_SVT_BYTEADDRESS_BUFFER: - case D3D_SVT_RWBYTEADDRESS_BUFFER: - case D3D_SVT_STRUCTURED_BUFFER: - case D3D_SVT_RWSTRUCTURED_BUFFER: - case D3D_SVT_APPEND_STRUCTURED_BUFFER: - case D3D_SVT_CONSUME_STRUCTURED_BUFFER: - break; - - default: - throw std::invalid_argument("Type (object) " + std::to_string(i) + - " is of invalid type"); - } - - if (type.Rows || type.Columns) - throw std::invalid_argument("Type (object) " + - std::to_string(i) + - " shouldn't have rows or columns"); - - break; - - default: - throw std::invalid_argument("Type " + std::to_string(i) + - " has an invalid class"); + // Only iterate on namespaces. + if (NamespaceDecl *DC = dyn_cast(*cur)) { + GlobalVariableAsExternByDefault(*DC); } } - - if (MakeNameLookupTable) - GenerateNameLookupTable(); -}; +} static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, ASTUnit::RemappedFile *pRemap, @@ -4042,20 +1342,18 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, //Reflect - DxcReflectionData refl; - ReflectHLSL(astHelper, refl, opts.AutoBindingSpace, reflectMask, - opts.DefaultRowMajor); - - //Print + DxcHLSLReflection refl(astHelper.compiler, *astHelper.tu, + opts.AutoBindingSpace, reflectMask, + opts.DefaultRowMajor); - RecursePrint(refl, 0, 0, 0); + refl.Printf(); //Test serialization std::vector bytes; refl.Dump(bytes); - DxcReflectionData deserialized(bytes, true); + DxcHLSLReflection deserialized(bytes, true); assert(deserialized == refl && "Dump or Deserialize doesn't match"); @@ -4064,11 +1362,11 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, //Test stripping symbols refl.StripSymbols(); - RecursePrint(refl, 0, 0, 0); + refl.Printf(); refl.Dump(bytes); - deserialized = DxcReflectionData(bytes, false); + deserialized = DxcHLSLReflection(bytes, false); assert(deserialized == refl && "Dump or Deserialize doesn't match"); From 0eeb1731fca2df70f8d99790ed52b22bf37a119e Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 2 Sep 2025 00:39:13 +0200 Subject: [PATCH 027/126] Removed rewriter option -consistent-bindings and now doing it in the dxil lowering properly, it's similar to -flegacy-resource-reservation but distinct in some key ways: the option only works for reserved registers and we need it to work on any register that has been compiled out. We also don't necessarily need the register to stay at the end of DXIL generation, in fact we'd rather not. Because having the register present can cause unintended performance penalties (for example, I use this reflection to know what transitions to issue) --- include/dxc/DXIL/DxilModule.h | 3 + include/dxc/HLSL/HLModule.h | 2 + include/dxc/Support/HLSLOptions.h | 2 +- include/dxc/Support/HLSLOptions.td | 5 +- lib/DXIL/DxilModule.cpp | 10 + lib/DxcSupport/HLSLOptions.cpp | 6 +- lib/HLSL/DxilCondenseResources.cpp | 6 +- lib/HLSL/DxilGenerationPass.cpp | 1 + lib/HLSL/HLModule.cpp | 18 +- .../include/clang/Frontend/CodeGenOptions.h | 2 + tools/clang/lib/CodeGen/CGHLSLMS.cpp | 2 + .../HLSL/rewriter/consistent_bindings.hlsl | 48 ---- .../clang/tools/dxcompiler/dxcompilerobj.cpp | 2 + .../clang/tools/libclang/dxcrewriteunused.cpp | 248 +----------------- tools/clang/unittests/HLSL/RewriterTest.cpp | 8 - 15 files changed, 48 insertions(+), 315 deletions(-) delete mode 100644 tools/clang/test/HLSL/rewriter/consistent_bindings.hlsl diff --git a/include/dxc/DXIL/DxilModule.h b/include/dxc/DXIL/DxilModule.h index 3f1ba12f86..5a91f0b204 100644 --- a/include/dxc/DXIL/DxilModule.h +++ b/include/dxc/DXIL/DxilModule.h @@ -287,6 +287,8 @@ class DxilModule { // Intermediate options that do not make it to DXIL void SetLegacyResourceReservation(bool legacyResourceReservation); bool GetLegacyResourceReservation() const; + void SetConsistentBindings(bool consistentBindings); + bool GetConsistentBindings() const; void ClearIntermediateOptions(); // Hull and Domain shaders. @@ -346,6 +348,7 @@ class DxilModule { enum IntermediateFlags : uint32_t { LegacyResourceReservation = 1 << 0, + ConsistentBindings = 1 << 1 }; llvm::LLVMContext &m_Ctx; diff --git a/include/dxc/HLSL/HLModule.h b/include/dxc/HLSL/HLModule.h index 653fc967d5..90d0c218cd 100644 --- a/include/dxc/HLSL/HLModule.h +++ b/include/dxc/HLSL/HLModule.h @@ -54,6 +54,7 @@ struct HLOptions { bDisableOptimizations(false), PackingStrategy(0), bUseMinPrecision(false), bDX9CompatMode(false), bFXCCompatMode(false), bLegacyResourceReservation(false), bForceZeroStoreLifetimes(false), + bConsistentBindings(false), unused(0) {} uint32_t GetHLOptionsRaw() const; void SetHLOptionsRaw(uint32_t data); @@ -70,6 +71,7 @@ struct HLOptions { unsigned bLegacyResourceReservation : 1; unsigned bForceZeroStoreLifetimes : 1; unsigned bResMayAlias : 1; + unsigned bConsistentBindings : 1; unsigned unused : 19; }; diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index 362482a981..bfa09f56bd 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -103,7 +103,6 @@ class DxcDefines { struct RewriterOpts { bool Unchanged = false; // OPT_rw_unchanged - bool ConsistentBindings = false; // OPT_rw_consistent_bindings bool ReflectHLSLBasics = false; // OPT_rw_reflect_hlsl_basics bool ReflectHLSLFunctions = false; // OPT_rw_reflect_hlsl_functions bool ReflectHLSLNamespaces = false; // OPT_rw_reflect_hlsl_namespaces @@ -235,6 +234,7 @@ class DxcOpts { std::string TimeTrace = ""; // OPT_ftime_trace[EQ] unsigned TimeTraceGranularity = 500; // OPT_ftime_trace_granularity_EQ bool VerifyDiagnostics = false; // OPT_verify + bool ConsistentBindings = false; // OPT_consistent_bindings // Optimization pass enables, disables and selects OptimizationToggles diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index 3bc9bafc78..9781ad6b2b 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -558,13 +558,14 @@ def getprivate : JoinedOrSeparate<["-", "/"], "getprivate">, Flags<[DriverOption def nologo : Flag<["-", "/"], "nologo">, Group, Flags<[DriverOption, HelpHidden]>, HelpText<"Suppress copyright message">; +def consistent_bindings : Flag<["-", "/"], "consistent-bindings">, Group, Flags<[CoreOption]>, + HelpText<"Generate bindings for registers with no pre-declared binding (consistently regardless of optimization).">; + ////////////////////////////////////////////////////////////////////////////// // Rewriter Options def rw_unchanged : Flag<["-", "/"], "unchanged">, Group, Flags<[RewriteOption]>, HelpText<"Rewrite HLSL, without changes.">; -def rw_consistent_bindings : Flag<["-", "/"], "consistent-bindings">, Group, Flags<[RewriteOption]>, - HelpText<"Generate bindings for registers that aren't fully qualified (to have consistent bindings).">; def rw_reflect_hlsl_basics : Flag<["-", "/"], "reflect-hlsl-basics">, Group, Flags<[RewriteOption]>, HelpText<"Reflect HLSL (registers, constants and annotations) and generate consistent bindings.">; def rw_reflect_hlsl_functions : Flag<["-", "/"], "reflect-hlsl-functions">, Group, Flags<[RewriteOption]>, diff --git a/lib/DXIL/DxilModule.cpp b/lib/DXIL/DxilModule.cpp index f4abdd15aa..d55923d964 100644 --- a/lib/DXIL/DxilModule.cpp +++ b/lib/DXIL/DxilModule.cpp @@ -586,6 +586,16 @@ bool DxilModule::GetLegacyResourceReservation() const { return (m_IntermediateFlags & LegacyResourceReservation) != 0; } +void DxilModule::SetConsistentBindings(bool consistentBindings) { + m_IntermediateFlags &= ~ConsistentBindings; + if (consistentBindings) + m_IntermediateFlags |= ConsistentBindings; +} + +bool DxilModule::GetConsistentBindings() const { + return (m_IntermediateFlags & ConsistentBindings) != 0; +} + void DxilModule::ClearIntermediateOptions() { m_IntermediateFlags = 0; } unsigned DxilModule::GetInputControlPointCount() const { diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index a28c999d5b..b6d38edd8a 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -871,6 +871,10 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, opts.TimeReport = Args.hasFlag(OPT_ftime_report, OPT_INVALID, false); opts.TimeTrace = Args.hasFlag(OPT_ftime_trace, OPT_INVALID, false) ? "-" : ""; opts.VerifyDiagnostics = Args.hasFlag(OPT_verify, OPT_INVALID, false); + + opts.ConsistentBindings = + Args.hasFlag(OPT_consistent_bindings, OPT_INVALID, false); + if (Args.hasArg(OPT_ftime_trace_EQ)) opts.TimeTrace = Args.getLastArgValue(OPT_ftime_trace_EQ); if (Arg *A = Args.getLastArg(OPT_ftime_trace_granularity_EQ)) { @@ -1349,8 +1353,6 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, // Rewriter Options if (flagsToInclude & hlsl::options::RewriteOption) { opts.RWOpt.Unchanged = Args.hasFlag(OPT_rw_unchanged, OPT_INVALID, false); - opts.RWOpt.ConsistentBindings = - Args.hasFlag(OPT_rw_consistent_bindings, OPT_INVALID, false); opts.RWOpt.ReflectHLSLBasics = Args.hasFlag(OPT_rw_reflect_hlsl_basics, OPT_INVALID, false); opts.RWOpt.ReflectHLSLFunctions = diff --git a/lib/HLSL/DxilCondenseResources.cpp b/lib/HLSL/DxilCondenseResources.cpp index 09dd9cea64..18dd741cc8 100644 --- a/lib/HLSL/DxilCondenseResources.cpp +++ b/lib/HLSL/DxilCondenseResources.cpp @@ -550,7 +550,8 @@ class DxilLowerCreateHandleForLib : public ModulePass { ResourceRegisterAllocator.GatherReservedRegisters(DM); // Remove unused resources. - DM.RemoveResourcesWithUnusedSymbols(); + if (!DM.GetConsistentBindings()) + DM.RemoveResourcesWithUnusedSymbols(); unsigned newResources = DM.GetCBuffers().size() + DM.GetUAVs().size() + DM.GetSRVs().size() + DM.GetSamplers().size(); @@ -571,6 +572,9 @@ class DxilLowerCreateHandleForLib : public ModulePass { bChanged |= ResourceRegisterAllocator.AllocateRegisters(DM); + if (DM.GetConsistentBindings()) + DM.RemoveResourcesWithUnusedSymbols(); + // Fill in top-level CBuffer variable usage bit UpdateCBufferUsage(); diff --git a/lib/HLSL/DxilGenerationPass.cpp b/lib/HLSL/DxilGenerationPass.cpp index c3a6ad7dfc..1686482518 100644 --- a/lib/HLSL/DxilGenerationPass.cpp +++ b/lib/HLSL/DxilGenerationPass.cpp @@ -155,6 +155,7 @@ void InitDxilModuleFromHLModule(HLModule &H, DxilModule &M, bool HasDebugInfo) { // bool m_bDisableOptimizations; M.SetDisableOptimization(H.GetHLOptions().bDisableOptimizations); M.SetLegacyResourceReservation(H.GetHLOptions().bLegacyResourceReservation); + M.SetConsistentBindings(H.GetHLOptions().bConsistentBindings); // bool m_bDisableMathRefactoring; // bool m_bEnableDoublePrecision; // bool m_bEnableDoubleExtensions; diff --git a/lib/HLSL/HLModule.cpp b/lib/HLSL/HLModule.cpp index bab6e23a30..ce6241a3b6 100644 --- a/lib/HLSL/HLModule.cpp +++ b/lib/HLSL/HLModule.cpp @@ -231,17 +231,18 @@ void HLModule::RemoveFunction(llvm::Function *F) { namespace { template bool RemoveResource(std::vector> &vec, - GlobalVariable *pVariable, bool keepAllocated) { + GlobalVariable *pVariable, bool keepAllocated, bool dontUpdateIds) { for (auto p = vec.begin(), e = vec.end(); p != e; ++p) { if ((*p)->GetGlobalSymbol() != pVariable) continue; - if (keepAllocated && (*p)->IsAllocated()) { + if ((keepAllocated && (*p)->IsAllocated()) || dontUpdateIds) { // Keep the resource, but it has no more symbol. (*p)->SetGlobalSymbol(UndefValue::get(pVariable->getType())); } else { // Erase the resource alltogether and update IDs of subsequent ones p = vec.erase(p); + for (e = vec.end(); p != e; ++p) { unsigned ID = (*p)->GetID() - 1; (*p)->SetID(ID); @@ -262,16 +263,21 @@ void HLModule::RemoveGlobal(llvm::GlobalVariable *GV) { // register range from being allocated to other resources. bool keepAllocated = GetHLOptions().bLegacyResourceReservation; + // Consistent bindings are different than -flegacy-resource-reservation; + // We need the IDs to stay the same, but it's fine to remove unused registers. + // It's actually wanted, because that allows us to know what registers are optimized out. + bool consistentBindings = GetHLOptions().bConsistentBindings; + // This could be considerably faster - check variable type to see which // resource type this is rather than scanning all lists, and look for // usage and removal patterns. - if (RemoveResource(m_CBuffers, GV, keepAllocated)) + if (RemoveResource(m_CBuffers, GV, keepAllocated, consistentBindings)) return; - if (RemoveResource(m_SRVs, GV, keepAllocated)) + if (RemoveResource(m_SRVs, GV, keepAllocated, consistentBindings)) return; - if (RemoveResource(m_UAVs, GV, keepAllocated)) + if (RemoveResource(m_UAVs, GV, keepAllocated, consistentBindings)) return; - if (RemoveResource(m_Samplers, GV, keepAllocated)) + if (RemoveResource(m_Samplers, GV, keepAllocated, consistentBindings)) return; // TODO: do m_TGSMVariables and m_StreamOutputs need maintenance? } diff --git a/tools/clang/include/clang/Frontend/CodeGenOptions.h b/tools/clang/include/clang/Frontend/CodeGenOptions.h index 859cba53da..2fe3d418b9 100644 --- a/tools/clang/include/clang/Frontend/CodeGenOptions.h +++ b/tools/clang/include/clang/Frontend/CodeGenOptions.h @@ -187,6 +187,8 @@ class CodeGenOptions : public CodeGenOptionsBase { bool HLSLOnlyWarnOnUnrollFail = false; /// Whether use legacy resource reservation. bool HLSLLegacyResourceReservation = false; + /// Whether to keep bindings consistent even if optimized out. + bool HLSLConsistentBindings = false; /// Set [branch] on every if. bool HLSLPreferControlFlow = false; /// Set [flatten] on every if. diff --git a/tools/clang/lib/CodeGen/CGHLSLMS.cpp b/tools/clang/lib/CodeGen/CGHLSLMS.cpp index b5add521a6..92964ba233 100644 --- a/tools/clang/lib/CodeGen/CGHLSLMS.cpp +++ b/tools/clang/lib/CodeGen/CGHLSLMS.cpp @@ -400,6 +400,8 @@ CGMSHLSLRuntime::CGMSHLSLRuntime(CodeGenModule &CGM) opts.PackingStrategy = CGM.getCodeGenOpts().HLSLSignaturePackingStrategy; opts.bLegacyResourceReservation = CGM.getCodeGenOpts().HLSLLegacyResourceReservation; + opts.bConsistentBindings = + CGM.getCodeGenOpts().HLSLConsistentBindings; opts.bForceZeroStoreLifetimes = CGM.getCodeGenOpts().HLSLForceZeroStoreLifetimes; diff --git a/tools/clang/test/HLSL/rewriter/consistent_bindings.hlsl b/tools/clang/test/HLSL/rewriter/consistent_bindings.hlsl deleted file mode 100644 index e12eed0789..0000000000 --- a/tools/clang/test/HLSL/rewriter/consistent_bindings.hlsl +++ /dev/null @@ -1,48 +0,0 @@ -//UAV - -RWByteAddressBuffer output1; -RWByteAddressBuffer output2; -RWByteAddressBuffer output3 : register(u0); -RWByteAddressBuffer output4 : register(space1); -RWByteAddressBuffer output5 : SEMA; -RWByteAddressBuffer output6; -RWByteAddressBuffer output7 : register(u1); -RWByteAddressBuffer output8[12] : register(u3); -RWByteAddressBuffer output9[12]; -RWByteAddressBuffer output10[33] : register(space1); -RWByteAddressBuffer output11[33] : register(space2); -RWByteAddressBuffer output12[33] : register(u0, space2); - -//SRV - -StructuredBuffer test; -ByteAddressBuffer input13 : SEMA; -ByteAddressBuffer input14; -ByteAddressBuffer input15 : register(t0); -ByteAddressBuffer input16[12] : register(t3); -ByteAddressBuffer input17[2] : register(space1); -ByteAddressBuffer input18[12] : register(t1, space1); -ByteAddressBuffer input19[3] : register(space1); -ByteAddressBuffer input20 : register(space1); - -//Sampler - -SamplerState sampler0; -SamplerState sampler1; -SamplerState sampler2 : register(s0); -SamplerState sampler3 : register(space1); -SamplerState sampler4 : register(s0, space1); - -//CBV - -cbuffer test : register(b0) { float a; }; -cbuffer test2 { float b; }; -cbuffer test3 : register(space1) { float c; }; -cbuffer test4 : register(space1) { float d; }; - -float e; - -[numthreads(16, 16, 1)] -void main(uint id : SV_DispatchThreadID) { - output2.Store(id * 4, 1); //Only use 1 output, but this won't result into output2 receiving wrong bindings -} diff --git a/tools/clang/tools/dxcompiler/dxcompilerobj.cpp b/tools/clang/tools/dxcompiler/dxcompilerobj.cpp index 84b568df9c..9989aa4150 100644 --- a/tools/clang/tools/dxcompiler/dxcompilerobj.cpp +++ b/tools/clang/tools/dxcompiler/dxcompilerobj.cpp @@ -1602,6 +1602,8 @@ class DxcCompiler : public IDxcCompiler3, compiler.getCodeGenOpts().HLSLAvoidControlFlow = Opts.AvoidFlowControl; compiler.getCodeGenOpts().HLSLLegacyResourceReservation = Opts.LegacyResourceReservation; + compiler.getCodeGenOpts().HLSLConsistentBindings = + Opts.ConsistentBindings; compiler.getCodeGenOpts().HLSLDefines = defines; compiler.getCodeGenOpts().HLSLPreciseOutputs = Opts.PreciseOutputs; compiler.getCodeGenOpts().MainFileName = pMainFile; diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 926a96e3b4..20e1b49d4a 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1036,247 +1036,6 @@ static void RemoveStaticDecls(DeclContext &Ctx) { } } -struct ResourceKey { - - uint32_t space; - DXIL::ResourceClass resourceClass; - - bool operator==(const ResourceKey &other) const { - return space == other.space && resourceClass == other.resourceClass; - } -}; - -namespace llvm { -template <> struct DenseMapInfo { - static inline ResourceKey getEmptyKey() { - return {~0u, DXIL::ResourceClass::Invalid}; - } - static inline ResourceKey getTombstoneKey() { - return {~0u - 1, DXIL::ResourceClass::Invalid}; - } - static unsigned getHashValue(const ResourceKey &K) { - return llvm::hash_combine(K.space, uint32_t(K.resourceClass)); - } - static bool isEqual(const ResourceKey &LHS, const ResourceKey &RHS) { - return LHS.space == RHS.space && LHS.resourceClass == RHS.resourceClass; - } -}; -} // namespace llvm - -using RegisterRange = std::pair; //(startReg, count) -using RegisterMap = - llvm::DenseMap>; - -struct UnresolvedRegister { - hlsl::DXIL::ResourceClass cls; - uint32_t arraySize; - RegisterAssignment *reg; - NamedDecl *ND; -}; - -using UnresolvedRegisters = llvm::SmallVector; - -// Find gap in register list and fill it - -uint32_t FillNextRegister(llvm::SmallVector &ranges, - uint32_t arraySize) { - - if (ranges.empty()) { - ranges.push_back({0, arraySize}); - return 0; - } - - size_t i = 0, j = ranges.size(); - size_t curr = 0; - - for (; i < j; ++i) { - - const RegisterRange &range = ranges[i]; - - if (range.first - curr >= arraySize) { - ranges.insert(ranges.begin() + i, RegisterRange{curr, arraySize}); - return curr; - } - - curr = range.first + range.second; - } - - ranges.emplace_back(RegisterRange{curr, arraySize}); - return curr; -} - -// Insert in the right place (keep sorted) - -void FillConsistentRegisterAt(llvm::SmallVector &ranges, - uint32_t registerNr, uint32_t arraySize, - clang::DiagnosticsEngine &diags, - const SourceLocation &location) { - - size_t i = 0, j = ranges.size(); - - for (; i < j; ++i) { - - const RegisterRange &range = ranges[i]; - - if (range.first > registerNr) { - - if (registerNr + arraySize > range.first) { - diags.Report(location, diag::err_hlsl_register_semantics_conflicting); - return; - } - - ranges.insert(ranges.begin() + i, RegisterRange{registerNr, arraySize}); - break; - } - - if (range.first + range.second > registerNr) { - diags.Report(location, diag::err_hlsl_register_semantics_conflicting); - return; - } - } - - if (i == j) - ranges.emplace_back(RegisterRange{registerNr, arraySize}); -} - -static void RegisterConsistentBinding(NamedDecl *ND, - UnresolvedRegisters &unresolvedRegisters, - RegisterMap &map, hlsl::DXIL::ResourceClass cls, - uint32_t arraySize, clang::DiagnosticsEngine &Diags, - uint32_t autoBindingSpace) { - - const ArrayRef &UA = ND->getUnusualAnnotations(); - - bool qualified = false; - RegisterAssignment *reg = nullptr; - - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { - - if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) - continue; - - reg = cast(*It); - - if (!reg->RegisterType) // Unqualified register assignment - break; - - uint32_t space = reg->RegisterSpace.hasValue() - ? reg->RegisterSpace.getValue() - : autoBindingSpace; - - qualified = true; - FillConsistentRegisterAt(map[ResourceKey{space, cls}], reg->RegisterNumber, arraySize, - Diags, ND->getLocation()); - break; - } - - if (!qualified) - unresolvedRegisters.emplace_back( - UnresolvedRegister{cls, arraySize, reg, ND}); -} - -static void GenerateConsistentBindings(DeclContext &Ctx, - uint32_t autoBindingSpace) { - - clang::DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); - - RegisterMap map; - UnresolvedRegisters unresolvedRegisters; - - // Fill up map with fully qualified registers to avoid colliding with them - // later - - for (Decl *it : Ctx.decls()) { - - // CBuffer has special logic, since it's not technically - - if (HLSLBufferDecl *CBuffer = dyn_cast(it)) { - RegisterConsistentBinding(CBuffer, unresolvedRegisters, map, - hlsl::DXIL::ResourceClass::CBuffer, 1, Diags, - autoBindingSpace); - continue; - } - - ValueDecl *VD = dyn_cast(it); - - if (!VD) - continue; - - std::string test = VD->getName(); - - uint32_t arraySize = 1; - QualType type = VD->getType(); - - while (const ConstantArrayType *arr = dyn_cast(type)) { - arraySize *= arr->getSize().getZExtValue(); - type = arr->getElementType(); - } - - if (!IsHLSLResourceType(type)) - continue; - - RegisterConsistentBinding(VD, unresolvedRegisters, map, GetHLSLResourceClass(type), - arraySize, Diags, autoBindingSpace); - } - - // Resolve unresolved registers (while avoiding collisions) - - for (const UnresolvedRegister ® : unresolvedRegisters) { - - uint32_t arraySize = reg.arraySize; - hlsl::DXIL::ResourceClass resClass = reg.cls; - - char prefix = 't'; - - switch (resClass) { - - case DXIL::ResourceClass::Sampler: - prefix = 's'; - break; - - case DXIL::ResourceClass::CBuffer: - prefix = 'b'; - break; - - case DXIL::ResourceClass::UAV: - prefix = 'u'; - break; - } - - uint32_t space = - reg.reg ? reg.reg->RegisterSpace.getValue() : autoBindingSpace; - - uint32_t registerNr = - FillNextRegister(map[ResourceKey{space, resClass}], arraySize); - - if (reg.reg) { - reg.reg->RegisterType = prefix; - reg.reg->RegisterNumber = registerNr; - reg.reg->setIsValid(true); - } else { - hlsl::RegisterAssignment - r; // Keep space empty to ensure space overrides still work fine - r.RegisterNumber = registerNr; - r.RegisterType = prefix; - r.setIsValid(true); - - llvm::SmallVector annotations; - - const ArrayRef &UA = - reg.ND->getUnusualAnnotations(); - - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) - annotations.emplace_back(*It); - - annotations.push_back(::new (Ctx.getParentASTContext()) - hlsl::RegisterAssignment(r)); - - reg.ND->setUnusualAnnotations(UnusualAnnotation::CopyToASTContextArray( - Ctx.getParentASTContext(), annotations.data(), annotations.size())); - } - } -} - static void GlobalVariableAsExternByDefault(DeclContext &Ctx) { for (auto it = Ctx.decls_begin(); it != Ctx.decls_end();) { auto cur = it++; @@ -1310,10 +1069,6 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, TranslationUnitDecl *tu = astHelper.tu; - if (opts.RWOpt.ConsistentBindings || opts.RWOpt.ReflectHLSLBasics) { - GenerateConsistentBindings(*tu, opts.AutoBindingSpace); - } - D3D12_HLSL_REFLECTION_FEATURE reflectMask = D3D12_HLSL_REFLECTION_FEATURE_NONE; @@ -1391,8 +1146,7 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, opts.RWOpt.RemoveUnusedFunctions, w); if (FAILED(hr)) return hr; - } else if (!opts.RWOpt.ConsistentBindings && - (reflectMask & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) { + } else if (reflectMask & D3D12_HLSL_REFLECTION_FEATURE_BASICS) { o << "// Rewrite unchanged result:\n"; } diff --git a/tools/clang/unittests/HLSL/RewriterTest.cpp b/tools/clang/unittests/HLSL/RewriterTest.cpp index 7adfd3f88e..1130772ff0 100644 --- a/tools/clang/unittests/HLSL/RewriterTest.cpp +++ b/tools/clang/unittests/HLSL/RewriterTest.cpp @@ -102,7 +102,6 @@ class RewriterTest : public ::testing::Test { TEST_METHOD(RunExtractUniforms) TEST_METHOD(RunGlobalsUsedInMethod) TEST_METHOD(RunRewriterFails) - TEST_METHOD(GenerateConsistentBindings) dxc::DxcDllSupport m_dllSupport; CComPtr m_pIncludeHandler; @@ -467,13 +466,6 @@ TEST_F(RewriterTest, RunSpirv) { VERIFY_IS_TRUE(strResult.find("namespace vk") == std::string::npos); } -TEST_F(RewriterTest, GenerateConsistentBindings) { - CheckVerifiesHLSL( - L"rewriter\\consistent_bindings.hlsl", - L"rewriter\\correct_rewrites\\consistent_bindings_gold.hlsl", - {L"-HV", L"2016", L"-consistent-bindings"}); -} - TEST_F(RewriterTest, RunStructMethods) { CheckVerifiesHLSL(L"rewriter\\struct-methods.hlsl", L"rewriter\\correct_rewrites\\struct-methods_gold.hlsl"); From 1933c5261141126ed931257fd7f097d98f7de090 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 9 Sep 2025 21:09:59 +0200 Subject: [PATCH 028/126] Removed binding point and binding space from DxcHLSLRegister since that depends on the backend. Made D3D12_HLSL_ANNOTATION which has a name and whether or not it is a builtin (MS annotation or C++ annotation). Started implementing the COM frontend. Fixed issue with AST that includes a Texture2DMS since apparently it includes sample count. Started separating the reflector from the rewriter. --- include/dxc/DxcReflection/DxcReflection.h | 56 +- include/dxc/dxctools.h | 128 ++- tools/clang/tools/dxcompiler/dxcapi.cpp | 3 + .../tools/dxcreflection/DxcReflection.cpp | 171 ++-- tools/clang/tools/libclang/CMakeLists.txt | 2 + tools/clang/tools/libclang/dxcreflector.cpp | 794 ++++++++++++++++++ .../clang/tools/libclang/dxcrewriteunused.cpp | 6 +- 7 files changed, 978 insertions(+), 182 deletions(-) create mode 100644 tools/clang/tools/libclang/dxcreflector.cpp diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 00e9bd3b39..29fb0f33b0 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -250,26 +250,13 @@ struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus uint8_t ReturnType; // D3D_RESOURCE_RETURN_TYPE uint8_t uFlags; - uint32_t BindPoint; - }; - uint64_t TypeDimensionReturnTypeFlagsBindPoint; - }; - - union { - struct { - uint32_t Space; uint32_t BindCount; }; - uint64_t SpaceBindCount; + uint64_t TypeDimensionReturnTypeFlagsBindCount; }; - union { - struct { - uint32_t NumSamples; - uint32_t NodeId; - }; - uint64_t NumSamplesNodeId; - }; + uint32_t Pad; + uint32_t NodeId; union { struct { @@ -280,15 +267,12 @@ struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus }; DxcHLSLRegister() = default; - DxcHLSLRegister(D3D_SHADER_INPUT_TYPE Type, uint32_t BindPoint, - uint32_t BindCount, uint32_t uFlags, - D3D_RESOURCE_RETURN_TYPE ReturnType, - D3D_SRV_DIMENSION Dimension, uint32_t NumSamples, - uint32_t Space, uint32_t NodeId, uint32_t ArrayId, - uint32_t BufferId) - : Type(Type), BindPoint(BindPoint), BindCount(BindCount), uFlags(uFlags), - ReturnType(ReturnType), Dimension(Dimension), - NumSamples(NumSamples), Space(Space), NodeId(NodeId), + DxcHLSLRegister(D3D_SHADER_INPUT_TYPE Type, uint32_t BindCount, + uint32_t uFlags, D3D_RESOURCE_RETURN_TYPE ReturnType, + D3D_SRV_DIMENSION Dimension, uint32_t NodeId, + uint32_t ArrayId, uint32_t BufferId) + : Type(Type), BindCount(BindCount), uFlags(uFlags), + ReturnType(ReturnType), Dimension(Dimension), NodeId(NodeId), ArrayId(ArrayId), BufferId(BufferId) { assert(Type >= D3D_SIT_CBUFFER && Type <= D3D_SIT_UAV_FEEDBACKTEXTURE && @@ -304,11 +288,9 @@ struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus } bool operator==(const DxcHLSLRegister &other) const { - return TypeDimensionReturnTypeFlagsBindPoint == - other.TypeDimensionReturnTypeFlagsBindPoint && - SpaceBindCount == other.SpaceBindCount && - NumSamplesNodeId == other.NumSamplesNodeId && - ArrayIdBufferId == other.ArrayIdBufferId; + return TypeDimensionReturnTypeFlagsBindCount == + other.TypeDimensionReturnTypeFlagsBindCount && + NodeId == other.NodeId && ArrayIdBufferId == other.ArrayIdBufferId; } }; @@ -429,9 +411,9 @@ struct DxcHLSLAnnotation { } }; -struct DxcHLSLReflection { +struct DxcHLSLReflectionData { - D3D12_HLSL_REFLECTION_FEATURE Features; + D3D12_HLSL_REFLECTION_FEATURE Features{}; std::vector Strings; std::unordered_map StringsToId; @@ -478,16 +460,16 @@ struct DxcHLSLReflection { void StripSymbols(); bool GenerateNameLookupTable(); - DxcHLSLReflection() = default; - DxcHLSLReflection(const std::vector &Bytes, + DxcHLSLReflectionData() = default; + DxcHLSLReflectionData(const std::vector &Bytes, bool MakeNameLookupTable); - DxcHLSLReflection(clang::CompilerInstance &Compiler, + DxcHLSLReflectionData(clang::CompilerInstance &Compiler, clang::TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, D3D12_HLSL_REFLECTION_FEATURE Features, bool DefaultRowMaj); - bool IsSameNonDebug(const DxcHLSLReflection &other) const { + bool IsSameNonDebug(const DxcHLSLReflectionData &other) const { return StringsNonDebug == other.StringsNonDebug && Nodes == other.Nodes && Registers == other.Registers && Functions == other.Functions && Enums == other.Enums && EnumValues == other.EnumValues && @@ -497,7 +479,7 @@ struct DxcHLSLReflection { Buffers == other.Buffers; } - bool operator==(const DxcHLSLReflection &other) const { + bool operator==(const DxcHLSLReflectionData &other) const { return IsSameNonDebug(other) && Strings == other.Strings && Sources == other.Sources && NodeSymbols == other.NodeSymbols && MemberNameIds == other.MemberNameIds && diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index dd4e3abb59..5434ee32d8 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -96,7 +96,9 @@ enum D3D12_HLSL_REFLECTION_FEATURE { D3D12_HLSL_REFLECTION_FEATURE_VARIABLES = 1 << 5, // Symbol info (stripping this will remove names and file location info) - D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO = 1 << 6 + D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO = 1 << 6, + + D3D12_HLSL_REFLECTION_FEATURE_ALL = D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - 1 }; inline D3D12_HLSL_REFLECTION_FEATURE &operator|=(D3D12_HLSL_REFLECTION_FEATURE &a, @@ -122,6 +124,7 @@ struct D3D12_HLSL_REFLECTION_DESC { UINT FunctionCount; UINT EnumCount; UINT StructCount; + UINT NodeCount; }; struct D3D12_HLSL_FUNCTION_DESC { @@ -156,6 +159,11 @@ struct D3D12_HLSL_ENUM_VALUE { INT64 Value; }; +struct D3D12_HLSL_ANNOTATION { + LPCSTR Name; + BOOL IsBuiltin; +}; + typedef interface ID3D12ShaderReflectionConstantBuffer ID3D12ShaderReflectionConstantBuffer; @@ -163,55 +171,123 @@ typedef struct _D3D12_SHADER_INPUT_BIND_DESC D3D12_SHADER_INPUT_BIND_DESC; typedef interface ID3D12ShaderReflectionVariable ID3D12ShaderReflectionVariable; typedef interface ID3D12FunctionParameterReflection ID3D12FunctionParameterReflection; typedef interface ID3D12ShaderReflectionType ID3D12ShaderReflectionType; +typedef interface IDxcHLSLReflection IDxcHLSLReflection; -CROSS_PLATFORM_UUIDOF(IDxcHLSLReflection, "7016f834-ae85-4c86-a473-8c2c981dd370") -struct IDxcHLSLReflection : public IUnknown { +// {7016F834-AE85-4C86-A473-8C2C981DD370} +interface DECLSPEC_UUID("7016f834-ae85-4c86-a473-8c2c981dd370") + IDxcHLSLReflection; +DEFINE_GUID(IID_IDxcHLSLReflection, 0x7016f834, 0xae85, 0x4c86, 0xa473, 0x8c, + 0x2c, 0x98, 0x1d, 0xd3, 0x70); - STDMETHOD(QueryInterface)(THIS_ _In_ REFIID iid, _Out_ LPVOID *ppv) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; +#undef INTERFACE +#define INTERFACE IDxcHLSLReflection + +DECLARE_INTERFACE(IDxcHLSLReflection) { STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_HLSL_REFLECTION_DESC *pDesc) PURE; - - STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetConstantBufferByIndex)(THIS_ _In_ UINT Index) PURE; - STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetConstantBufferByName)(THIS_ _In_ LPCSTR Name) PURE; - - STDMETHOD(GetResourceBindingDesc)(THIS_ _In_ UINT ResourceIndex, - _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE; - STDMETHOD(GetResourceBindingDescByName)(THIS_ _In_ LPCSTR Name, - _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex) + (THIS_ _In_ UINT Index) PURE; + + // The D3D12_SHADER_INPUT_BIND_DESC permits providing invalid Space and + // BindPoint. In the future, implementations could decide to return this + // depending on the backend. But since this is a HLSL frontend thing, we don't + // know the bindings on the backend. + + STDMETHOD(GetResourceBindingDesc) + (THIS_ _In_ UINT ResourceIndex, _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) + PURE; STDMETHOD(GetFunctionDesc) - (THIS_ _In_ UINT FunctionIndex, - THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) PURE; + (THIS_ _In_ UINT FunctionIndex, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) + PURE; // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE; STDMETHOD(GetStructTypeByIndex) - (THIS_ _In_ UINT StructIndex, - _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; - - STDMETHOD(GetStructTypeByName) - (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + (THIS_ _In_ UINT StructIndex, _Outptr_ ID3D12ShaderReflectionType **ppType) + PURE; STDMETHOD(GetEnumDesc) (THIS_ _In_ UINT EnumIndex, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; - STDMETHOD(GetEnumDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; - STDMETHOD(GetEnumValueByIndex) (THIS_ _In_ UINT EnumIndex, _In_ UINT ValueIndex, _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) PURE; STDMETHOD(GetAnnotationCount) - (THIS_ _In_ LPCSTR SymbolName, _Out_ UINT *pCount) PURE; + (THIS_ _In_ UINT SymbolId, _Out_ UINT *pCount) PURE; STDMETHOD(GetAnnotationByIndex) + (THIS_ _In_ UINT SymbolId, _In_ UINT Index, + _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) PURE; + + // Name helpers; only available if symbols aren't stripped + + STDMETHOD(GetSymbolByName) + (THIS_ _In_ LPCSTR Name, _Out_ UINT *pSymbolId) PURE; + + STDMETHOD(GetSymbolName) + (THIS_ _In_ UINT SymbolId, _Out_ LPCSTR *pSymbolName) PURE; + + STDMETHOD(GetAnnotationCountByName) + (THIS_ _In_ LPCSTR SymbolName, _Out_ UINT *pCount) PURE; + + STDMETHOD(GetAnnotationByIndexAndName) (THIS_ _In_ LPCSTR SymbolName, _In_ UINT Index, - _Outptr_result_z_ LPCSTR *ppAnnotationText) PURE; + _Out_ D3D12_HLSL_ANNOTATION *ppAnnotationText) PURE; + + STDMETHOD(GetEnumDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; + + STDMETHOD(GetEnumValueByNameAndIndex) + (THIS_ _In_ LPCSTR Name, _In_ UINT ValueIndex, + _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByName) + (THIS_ _In_ LPCSTR Name) PURE; + + STDMETHOD(GetFunctionDescByName) + (THIS_ _In_ LPCSTR Name, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC * pDesc) PURE; + + STDMETHOD(GetResourceBindingDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE; + + STDMETHOD(GetStructTypeByName) + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; +}; + +#undef INTERFACE + +CLSID_SCOPE const CLSID + CLSID_DxcReflector = {/* ba5a8d8e-bf71-435a-977f-1677d7bcccc1 */ + 0xba5a8d8e, + 0xbf71, + 0x435a, + {0x16, 0x77, 0xd7, 0xbc, 0xcc, 0xc1}}; + +CROSS_PLATFORM_UUIDOF(IDxcHLSLReflector, "ba5a8d8e-bf71-435a-977f-1677d7bcccc1") +struct IDxcHLSLReflector : public IUnknown { + + virtual HRESULT STDMETHODCALLTYPE FromSource( + IDxcBlobEncoding *pSource, + // Optional file name for pSource. Used in errors and include handlers. + LPCWSTR pSourceName, + // Compiler arguments + LPCWSTR *pArguments, UINT32 argCount, + // Defines + DxcDefine *pDefines, UINT32 defineCount, + // user-provided interface to handle #include directives (optional) + IDxcIncludeHandler *pIncludeHandler, + IDxcOperationResult **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE + FromBlob(IDxcBlob *data, IDxcHLSLReflection **ppReflection) = 0; + + virtual HRESULT STDMETHODCALLTYPE ToBlob(IDxcHLSLReflection *reflection, + IDxcBlob **ppResult) = 0; }; #endif diff --git a/tools/clang/tools/dxcompiler/dxcapi.cpp b/tools/clang/tools/dxcompiler/dxcapi.cpp index d4e85bc35c..703b202025 100644 --- a/tools/clang/tools/dxcompiler/dxcapi.cpp +++ b/tools/clang/tools/dxcompiler/dxcapi.cpp @@ -33,6 +33,7 @@ HRESULT CreateDxcIntelliSense(REFIID riid, _Out_ LPVOID *ppv); HRESULT CreateDxcCompilerArgs(REFIID riid, _Out_ LPVOID *ppv); HRESULT CreateDxcUtils(REFIID riid, _Out_ LPVOID *ppv); HRESULT CreateDxcRewriter(REFIID riid, _Out_ LPVOID *ppv); +HRESULT CreateDxcReflector(REFIID riid, _Out_ LPVOID *ppv); HRESULT CreateDxcValidator(REFIID riid, _Out_ LPVOID *ppv); HRESULT CreateDxcAssembler(REFIID riid, _Out_ LPVOID *ppv); HRESULT CreateDxcOptimizer(REFIID riid, _Out_ LPVOID *ppv); @@ -92,6 +93,8 @@ static HRESULT ThreadMallocDxcCreateInstance(REFCLSID rclsid, REFIID riid, hr = CreateDxcPdbUtils(riid, ppv); } else if (IsEqualCLSID(rclsid, CLSID_DxcRewriter)) { hr = CreateDxcRewriter(riid, ppv); + } else if (IsEqualCLSID(rclsid, CLSID_DxcReflector)) { + hr = CreateDxcReflector(riid, ppv); } else if (IsEqualCLSID(rclsid, CLSID_DxcLinker)) { hr = CreateDxcLinker(riid, ppv); } diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 94b36a9a1f..cdf0f76c33 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -28,10 +28,9 @@ struct DxcRegisterTypeInfo { D3D_SHADER_INPUT_FLAGS RegisterFlags; D3D_SRV_DIMENSION TextureDimension; D3D_RESOURCE_RETURN_TYPE TextureValue; - uint32_t SampleCount; }; -static uint32_t RegisterString(DxcHLSLReflection &Refl, +static uint32_t RegisterString(DxcHLSLReflectionData &Refl, const std::string &Name, bool isNonDebug) { assert(Name.size() < 32768 && "Strings are limited to 32767"); @@ -66,7 +65,7 @@ static uint32_t RegisterString(DxcHLSLReflection &Refl, return stringId; } -static uint32_t PushNextNodeId(DxcHLSLReflection &Refl, const SourceManager &SM, +static uint32_t PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, const LangOptions &LangOpts, const std::string &UnqualifiedName, Decl *Decl, DxcHLSLNodeType Type, uint32_t ParentNodeId, @@ -205,7 +204,6 @@ static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, DxcRegisterTypeInfo type = {}; type.RegisterType = IsWrite ? D3D_SIT_UAV_RWTYPED : D3D_SIT_TEXTURE; - type.SampleCount = (uint32_t)-1; //Parse return type and dimensions @@ -216,7 +214,14 @@ static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, const ArrayRef& textureParams = textureTemplate->getTemplateArgs().asArray(); - assert(textureParams.size() == 1 && + bool shouldBeTexture2DMS = textureParams.size() == 2; + + if (shouldBeTexture2DMS) + assert(textureParams[0].getKind() == TemplateArgument::Type && + textureParams[1].getKind() == TemplateArgument::Integral && + "Expected template args"); + + else assert(textureParams.size() == 1 && textureParams[0].getKind() == TemplateArgument::Type && "Expected template args"); @@ -290,6 +295,7 @@ static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, //Parse type if (TypeName == "Buffer") { + assert(!shouldBeTexture2DMS && "Buffer expected but got Buffer"); type.TextureDimension = D3D_SRV_DIMENSION_BUFFER; return type; } @@ -321,10 +327,12 @@ static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, else if (TypeName == "Texture1D") type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE1D; - else if (TypeName == "Texture2DMS") { + else if (TypeName == "Texture2DMS") type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2DMS; - type.SampleCount = 0; - } + + assert((shouldBeTexture2DMS == + (type.TextureDimension == D3D_SRV_DIMENSION_TEXTURE2DMS)) && + "Texture2DMS used with Texture2D syntax or reverse"); if (isArray) //Arrays are always 1 behind the regular type type.TextureDimension = (D3D_SRV_DIMENSION)(type.TextureDimension + 1); @@ -357,16 +365,6 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, DxcRegisterTypeInfo info = {}; - if (const ClassTemplateSpecializationDecl *spec = - dyn_cast(recordDecl)) { - - const ArrayRef &array = - spec->getTemplateArgs().asArray(); - - if (array.size() == 1) - info.SampleCount = (uint32_t) (ASTCtx.getTypeSize(array[0].getAsType()) / 8); - } - if (typeName == "AppendStructuredBuffer") { info.RegisterType = D3D_SIT_UAV_APPEND_STRUCTURED; return info; @@ -379,7 +377,6 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, if (typeName == "RaytracingAccelerationStructure") { info.RegisterType = D3D_SIT_RTACCELERATIONSTRUCTURE; - info.SampleCount = (uint32_t)-1; return info; } @@ -414,7 +411,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); } -static uint32_t PushArray(DxcHLSLReflection &Refl, uint32_t ArraySizeFlat, +static uint32_t PushArray(DxcHLSLReflectionData &Refl, uint32_t ArraySizeFlat, const std::vector &ArraySize) { if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) @@ -450,7 +447,7 @@ static uint32_t PushArray(DxcHLSLReflection &Refl, uint32_t ArraySizeFlat, return arrayId; } -uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflection &Refl, +uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, QualType Original, bool DefaultRowMaj) { // Unwrap array @@ -803,24 +800,11 @@ static void FillReflectionRegisterAt( const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, ValueDecl *ValDesc, const std::vector &ArraySize, - DxcHLSLReflection &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId, + DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId, bool DefaultRowMaj) { ArrayRef UA = ValDesc->getUnusualAnnotations(); - hlsl::RegisterAssignment *reg = nullptr; - - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { - - if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) - continue; - - reg = cast(*It); - } - - assert(reg && "Found a register missing a RegisterAssignment, even though " - "GenerateConsistentBindings should have already generated it"); - DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); uint32_t nodeId = PushNextNodeId( @@ -838,16 +822,11 @@ static void FillReflectionRegisterAt( } DxcHLSLRegister regD3D12 = { - inputType.RegisterType, - reg->RegisterNumber, ArraySizeFlat, (uint32_t)inputType.RegisterFlags, inputType.TextureValue, inputType.TextureDimension, - inputType.SampleCount, - reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() - : AutoBindingSpace, nodeId, arrayId, bufferId @@ -918,7 +897,7 @@ class PrintfStream : public llvm::raw_ostream { template void RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, - DxcHLSLReflection &Refl, const T &Decls, + DxcHLSLReflectionData &Refl, const T &Decls, bool DefaultRowMaj, uint32_t ParentId) { for (Decl *decl : Decls) { @@ -946,7 +925,7 @@ void RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, } } -uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcHLSLReflection &Refl, +uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, const SourceManager &SM, DeclContext *Buffer, uint32_t NodeId, D3D_CBUFFER_TYPE Type, bool DefaultRowMaj) { @@ -963,7 +942,7 @@ uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcHLSLReflection &Refl, /* static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, - DxcHLSLReflection &Refl, const SourceManager &SM, + DxcHLSLReflectionData &Refl, const SourceManager &SM, uint32_t ParentNodeId) { PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); @@ -1013,7 +992,7 @@ static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, - DxcHLSLReflection &Refl, + DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, @@ -1051,21 +1030,6 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (Depth != 0) continue; - hlsl::RegisterAssignment *reg = nullptr; - ArrayRef UA = CBuffer->getUnusualAnnotations(); - - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { - - if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_RegisterAssignment) - continue; - - reg = cast(*It); - } - - assert(reg && - "Found a cbuffer missing a RegisterAssignment, even though " - "GenerateConsistentBindings should have already generated it"); - uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), CBuffer->getName(), CBuffer, DxcHLSLNodeType::Register, ParentNodeId, @@ -1075,20 +1039,14 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, D3D_CT_CBUFFER, DefaultRowMaj); DxcHLSLRegister regD3D12 = { - D3D_SIT_CBUFFER, - reg->RegisterNumber, 1, - (uint32_t) D3D_SIF_USERPACKED, - (D3D_RESOURCE_RETURN_TYPE) 0, + (uint32_t)D3D_SIF_USERPACKED, + (D3D_RESOURCE_RETURN_TYPE)0, D3D_SRV_DIMENSION_UNKNOWN, 0, - reg->RegisterSpace.hasValue() ? reg->RegisterSpace.getValue() - : AutoBindingSpace, nodeId, - (uint32_t)-1, - bufferId - }; + bufferId}; Refl.Registers.push_back(regD3D12); } @@ -1257,7 +1215,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, } } -DxcHLSLReflection::DxcHLSLReflection(clang::CompilerInstance &Compiler, +DxcHLSLReflectionData::DxcHLSLReflectionData(clang::CompilerInstance &Compiler, clang::TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, D3D12_HLSL_REFLECTION_FEATURE Features, @@ -1284,31 +1242,7 @@ DxcHLSLReflection::DxcHLSLReflection(clang::CompilerInstance &Compiler, //TODO: Debug print code -static char RegisterGetSpaceChar(const DxcHLSLRegister ®) { - - switch (reg.Type) { - - case D3D_SIT_UAV_RWTYPED: - case D3D_SIT_UAV_RWSTRUCTURED: - case D3D_SIT_UAV_RWBYTEADDRESS: - case D3D_SIT_UAV_APPEND_STRUCTURED: - case D3D_SIT_UAV_CONSUME_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: - case D3D_SIT_UAV_FEEDBACKTEXTURE: - return 'u'; - - case D3D_SIT_CBUFFER: - return 'b'; - - case D3D_SIT_SAMPLER: - return 's'; - - default: - return 't'; - } -} - -static std::string RegisterGetArraySize(const DxcHLSLReflection &Refl, const DxcHLSLRegister ®) { +static std::string RegisterGetArraySize(const DxcHLSLReflectionData &Refl, const DxcHLSLRegister ®) { if (reg.ArrayId != (uint32_t)-1) { @@ -1341,7 +1275,7 @@ static std::string NodeTypeToString(DxcHLSLNodeType type) { return arr[(int)type]; } -static std::string GetBuiltinTypeName(const DxcHLSLReflection &Refl, +static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, const DxcHLSLType &Type) { std::string type; @@ -1438,7 +1372,7 @@ static std::string GetBuiltinTypeName(const DxcHLSLReflection &Refl, return type; } -static std::string PrintTypeInfo(const DxcHLSLReflection &Refl, +static std::string PrintTypeInfo(const DxcHLSLReflectionData &Refl, const DxcHLSLType &Type, const std::string &PreviousTypeName) { @@ -1467,7 +1401,7 @@ static std::string PrintTypeInfo(const DxcHLSLReflection &Refl, return result; } -static void RecursePrintType(const DxcHLSLReflection &Refl, uint32_t TypeId, +static void RecursePrintType(const DxcHLSLReflectionData &Refl, uint32_t TypeId, uint32_t Depth, const char *Prefix = "") { const DxcHLSLType &type = Refl.Types[TypeId]; @@ -1496,7 +1430,7 @@ static void RecursePrintType(const DxcHLSLReflection &Refl, uint32_t TypeId, } } -uint32_t RecursePrint(const DxcHLSLReflection &Refl, uint32_t NodeId, +uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, uint32_t Depth, uint32_t IndexInParent) { const DxcHLSLNode &node = Refl.Nodes[NodeId]; @@ -1528,11 +1462,15 @@ uint32_t RecursePrint(const DxcHLSLReflection &Refl, uint32_t NodeId, switch (node.GetNodeType()) { case DxcHLSLNodeType::Register: { + const DxcHLSLRegister ® = Refl.Registers[localId]; - printf("%s%s : register(%c%u, space%u);\n", + + if (reg.ArrayId == (uint32_t)-1 && reg.BindCount == 1) + break; + + printf("%s%s\n", std::string(Depth, '\t').c_str(), - RegisterGetArraySize(Refl, reg).c_str(), RegisterGetSpaceChar(reg), - reg.BindPoint, reg.Space); + RegisterGetArraySize(Refl, reg).c_str()); break; } @@ -1765,7 +1703,7 @@ void Consume(const std::vector &Bytes, uint64_t &Offset, static constexpr uint32_t DxcReflectionDataMagic = DXC_FOURCC('D', 'H', 'R', 'D'); static constexpr uint16_t DxcReflectionDataVersion = 0; -void DxcHLSLReflection::StripSymbols() { +void DxcHLSLReflectionData::StripSymbols() { Strings.clear(); StringsToId.clear(); Sources.clear(); @@ -1779,7 +1717,7 @@ void DxcHLSLReflection::StripSymbols() { Features &= ~D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; } -void RecurseNameGenerationType(DxcHLSLReflection &Refl, uint32_t TypeId, +void RecurseNameGenerationType(DxcHLSLReflectionData &Refl, uint32_t TypeId, uint32_t LocalId, const std::string &Parent) { const DxcHLSLType &type = Refl.Types[TypeId]; @@ -1798,7 +1736,7 @@ void RecurseNameGenerationType(DxcHLSLReflection &Refl, uint32_t TypeId, } } -uint32_t RecurseNameGeneration(DxcHLSLReflection &Refl, uint32_t NodeId, +uint32_t RecurseNameGeneration(DxcHLSLReflectionData &Refl, uint32_t NodeId, uint32_t LocalId, const std::string &Parent, bool IsDot) { @@ -1840,7 +1778,7 @@ uint32_t RecurseNameGeneration(DxcHLSLReflection &Refl, uint32_t NodeId, return node.GetChildCount(); } -bool DxcHLSLReflection::GenerateNameLookupTable() { +bool DxcHLSLReflectionData::GenerateNameLookupTable() { if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) || Nodes.empty()) return false; @@ -1850,12 +1788,13 @@ bool DxcHLSLReflection::GenerateNameLookupTable() { return true; } -void DxcHLSLReflection::Dump(std::vector &Bytes) const { +void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { uint64_t toReserve = sizeof(DxcHLSLHeader); - Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, - Enums, EnumValues, Annotations, ArraySizes, MemberTypeIds, MemberNameIds, Types, TypeNameIds, Buffers); + Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, + Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, + Arrays, MemberTypeIds, MemberNameIds, Types, TypeNameIds, Buffers); Bytes.resize(toReserve); @@ -1875,12 +1814,12 @@ void DxcHLSLReflection::Dump(std::vector &Bytes) const { toReserve += sizeof(DxcHLSLHeader); Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, - NodeSymbols, Registers, - Functions, Enums, EnumValues, Annotations, ArraySizes, MemberTypeIds, - MemberNameIds, Types, TypeNameIds, Buffers); + NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, + ArraySizes, Arrays, MemberTypeIds, MemberNameIds, Types, TypeNameIds, + Buffers); } -DxcHLSLReflection::DxcHLSLReflection(const std::vector &Bytes, +DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes, bool MakeNameLookupTable) { uint64_t off = 0; @@ -1909,9 +1848,9 @@ DxcHLSLReflection::DxcHLSLReflection(const std::vector &Bytes, NodeSymbols, nodeSymbolCount, Registers, header.Registers, Functions, header.Functions, Enums, header.Enums, EnumValues, header.EnumValues, Annotations, header.Annotations, ArraySizes, header.ArraySizes, - MemberTypeIds, header.Members, MemberNameIds, memberSymbolCount, - Types, header.Types, TypeNameIds, typeSymbolCount, Buffers, - header.Buffers); + Arrays, header.Arrays, MemberTypeIds, header.Members, MemberNameIds, + memberSymbolCount, Types, header.Types, TypeNameIds, typeSymbolCount, + Buffers, header.Buffers); // Validation errors are throws to prevent accessing invalid data @@ -2246,6 +2185,6 @@ DxcHLSLReflection::DxcHLSLReflection(const std::vector &Bytes, }; -void DxcHLSLReflection::Printf() const { RecursePrint(*this, 0, 0, 0); } +void DxcHLSLReflectionData::Printf() const { RecursePrint(*this, 0, 0, 0); } } diff --git a/tools/clang/tools/libclang/CMakeLists.txt b/tools/clang/tools/libclang/CMakeLists.txt index 724d24ccc8..28374eca80 100644 --- a/tools/clang/tools/libclang/CMakeLists.txt +++ b/tools/clang/tools/libclang/CMakeLists.txt @@ -30,6 +30,7 @@ set(SOURCES IndexingContext.cpp dxcisenseimpl.cpp # HLSL Change dxcrewriteunused.cpp # HLSL Change + dxcreflector.cpp # HLSL Change ADDITIONAL_HEADERS CIndexDiagnostic.h @@ -70,6 +71,7 @@ set(SOURCES IndexingContext.cpp dxcisenseimpl.cpp # HLSL Change dxcrewriteunused.cpp # HLSL Change + dxcreflector.cpp # HLSL Change ADDITIONAL_HEADERS CIndexDiagnostic.h diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp new file mode 100644 index 0000000000..0a660eb10d --- /dev/null +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -0,0 +1,794 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// dxcreflector.cpp // +// Copyright (C) Microsoft Corporation. All rights reserved. // +// This file is distributed under the University of Illinois Open Source // +// License. See LICENSE.TXT for details. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/HlslTypes.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TargetOptions.h" +#include "clang/Frontend/ASTUnit.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Lex/HLSLMacroExpander.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/ParseAST.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Sema/SemaConsumer.h" +#include "clang/Sema/SemaHLSL.h" +#include "llvm/Support/Host.h" + +#include "dxc/Support/FileIOHelper.h" +#include "dxc/Support/Global.h" +#include "dxc/Support/Unicode.h" +#include "dxc/Support/WinIncludes.h" +#include "dxc/Support/microcom.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MSFileSystem.h" + +#include "dxc/Support/DxcLangExtensionsHelper.h" +#include "dxc/Support/HLSLOptions.h" +#include "dxc/Support/dxcapi.impl.h" +#include "dxc/Support/dxcfilesystem.h" +#include "dxc/dxcapi.internal.h" +#include "dxc/dxctools.h" + +#include "dxc/DxcReflection/DxcReflection.h" + +using namespace llvm; +using namespace clang; +using namespace hlsl; + +struct ASTHelper { + CompilerInstance compiler; + TranslationUnitDecl *tu; + ParsedSemanticDefineList semanticMacros; + ParsedSemanticDefineList userMacros; + bool bHasErrors; +}; + +struct DxcHLSLReflection : public IDxcHLSLReflection { + + DxcHLSLReflectionData data{}; + + DxcHLSLReflection() = default; + DxcHLSLReflection(DxcHLSLReflectionData &&moved) : data(moved) { + data.GenerateNameLookupTable(); + } + + DxcHLSLReflection &operator=(DxcHLSLReflection &&moved) { + data = std::move(moved.data); + data.GenerateNameLookupTable(); + return *this; + } + + //Conversion of DxcHLSL structs to D3D12_HLSL standardized structs + + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_HLSL_REFLECTION_DESC *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + *pDesc = {data.Features, + 0, //TODO: data.ConstantBuffers, + uint32_t(data.Registers.size()), + uint32_t(data.Functions.size()), + uint32_t(data.Enums.size()), + 0, // TODO: Structs + uint32_t(data.Nodes.size())}; + + return S_OK; + } + + STDMETHOD(GetResourceBindingDesc) + (THIS_ _In_ UINT ResourceIndex, + _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + if (ResourceIndex >= data.Registers.size()) + return E_INVALIDARG; + + const DxcHLSLRegister ® = data.Registers[ResourceIndex]; + + LPCSTR name = + data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + ? data.Strings[data.NodeSymbols[reg.NodeId].NameId].c_str() + : ""; + + *pDesc = D3D12_SHADER_INPUT_BIND_DESC{ + name, + (D3D_SHADER_INPUT_TYPE)reg.Type, + uint32_t(-1), //Invalid bindPoint, depending on backend we might want to change it + reg.BindCount, + + reg.uFlags, + (D3D_RESOURCE_RETURN_TYPE) reg.ReturnType, + (D3D_SRV_DIMENSION) reg.Dimension, + uint32_t(-1), // Also no valid data depending on backend + uint32_t(-1), //Invalid space (see bindPoint ^) + reg.NodeId + }; + + return S_OK; + } + + STDMETHOD(GetEnumDesc) + (THIS_ _In_ UINT EnumIndex, _Out_ D3D12_HLSL_ENUM_DESC* pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + if (EnumIndex >= data.Enums.size()) + return E_INVALIDARG; + + const DxcHLSLEnumDesc &enm = data.Enums[EnumIndex]; + + LPCSTR name = + data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + ? data.Strings[data.NodeSymbols[enm.NodeId].NameId].c_str() + : ""; + + *pDesc = D3D12_HLSL_ENUM_DESC{ + name, uint32_t(data.Nodes[enm.NodeId].GetChildCount()), enm.Type}; + + return S_OK; + } + + STDMETHOD(GetEnumValueByIndex) + (THIS_ _In_ UINT EnumIndex, _In_ UINT ValueIndex, + _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) override { + + IFR(ZeroMemoryToOut(pValueDesc)); + + if (EnumIndex >= data.Enums.size()) + return E_INVALIDARG; + + const DxcHLSLEnumDesc &enm = data.Enums[EnumIndex]; + const DxcHLSLNode &parent = data.Nodes[enm.NodeId]; + + if (ValueIndex >= parent.GetChildCount()) + return E_INVALIDARG; + + LPCSTR name = + data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + ? data.Strings[data.NodeSymbols[enm.NodeId].NameId].c_str() + : ""; + + const DxcHLSLNode &node = data.Nodes[enm.NodeId + 1 + ValueIndex]; + + *pValueDesc = + D3D12_HLSL_ENUM_VALUE{name, data.EnumValues[node.GetLocalId()].Value}; + + return S_OK; + } + + STDMETHOD(GetAnnotationCount) + (THIS_ _In_ UINT SymbolId, _Out_ UINT *pCount) override { + + IFR(ZeroMemoryToOut(pCount)); + + if (SymbolId >= data.Nodes.size()) + return E_INVALIDARG; + + *pCount = data.Nodes[SymbolId].GetAnnotationCount(); + return S_OK; + } + + STDMETHOD(GetAnnotationByIndex) + (THIS_ _In_ UINT SymbolId, _In_ UINT Index, + _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) override { + + IFR(ZeroMemoryToOut(pAnnotation)); + + if (SymbolId >= data.Nodes.size()) + return E_INVALIDARG; + + const DxcHLSLNode &node = data.Nodes[SymbolId]; + + if (Index >= node.GetAnnotationCount()) + return E_INVALIDARG; + + const DxcHLSLAnnotation &annotation = + data.Annotations[node.GetAnnotationStart() + Index]; + + *pAnnotation = D3D12_HLSL_ANNOTATION{ + data.StringsNonDebug[annotation.GetStringNonDebug()].c_str(), + annotation.GetIsBuiltin()}; + + return S_OK; + } + + STDMETHOD(GetFunctionDesc) + (THIS_ _In_ UINT FunctionIndex, + THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + if (FunctionIndex >= data.Functions.size()) + return E_INVALIDARG; + + const DxcHLSLFunction &func = data.Functions[FunctionIndex]; + + LPCSTR name = + data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + ? data.Strings[data.NodeSymbols[func.NodeId].NameId].c_str() + : ""; + + *pDesc = D3D12_HLSL_FUNCTION_DESC{name, func.GetNumParameters(), + func.HasReturn()}; + + return S_OK; + } + + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex) + (THIS_ _In_ UINT Index) PURE; + + // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. + STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) + (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE; + + STDMETHOD(GetStructTypeByIndex) + (THIS_ _In_ UINT StructIndex, + _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + + //Helper for conversion between symbol names + + // TODO: GetSymbolByName + // TODO: GetConstantBufferByIndex + // TODO: GetConstantBufferByName + // TODO: GetFunctionParameter + // TODO: GetStructByIndex + // TODO: GetStructTypeByName + // TODO: GetStructTypeByIndex + // TODO: Node api, types, arrays + + STDMETHOD(GetSymbolByName) + (THIS_ _In_ LPCSTR Name, _Out_ UINT *pSymbolId) override; //TODO: 1st bit: isMember, else + + STDMETHOD(GetSymbolName) + (THIS_ _In_ UINT SymbolId, _Out_ LPCSTR *pSymbolName) override { + + IFR(ZeroMemoryToOut(pSymbolName)); + + if (!(data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO)) + return E_UNEXPECTED; + + if (SymbolId >> 31) { + + SymbolId = SymbolId << 1 >> 1; + + if (SymbolId >= data.MemberNameIds.size()) + return E_INVALIDARG; + + *pSymbolName = data.Strings[data.MemberNameIds[SymbolId]].c_str(); + return S_OK; + } + + if (SymbolId >= data.NodeSymbols.size()) + return E_INVALIDARG; + + *pSymbolName = data.Strings[data.NodeSymbols[SymbolId].NameId].c_str(); + return S_OK; + } + + STDMETHOD(GetResourceBindingDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + UINT symbolId = UINT(-1); + IFR(GetSymbolByName(Name, &symbolId)); + + if (symbolId >> 31) + return E_INVALIDARG; + + const DxcHLSLNode &node = data.Nodes[symbolId]; + + if (node.GetNodeType() != DxcHLSLNodeType::Register) + return E_INVALIDARG; + + return GetResourceBindingDesc(node.GetLocalId(), pDesc); + } + + STDMETHOD(GetEnumDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + UINT symbolId = UINT(-1); + IFR(GetSymbolByName(Name, &symbolId)); + + if (symbolId >> 31) + return E_INVALIDARG; + + const DxcHLSLNode &node = data.Nodes[symbolId]; + + if (node.GetNodeType() != DxcHLSLNodeType::Enum) + return E_INVALIDARG; + + return GetEnumDesc(node.GetLocalId(), pDesc); + } + + STDMETHOD(GetEnumValueByNameAndIndex) + (THIS_ _In_ LPCSTR Name, _In_ UINT ValueIndex, + _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) override { + + IFR(ZeroMemoryToOut(pValueDesc)); + + UINT symbolId = UINT(-1); + IFR(GetSymbolByName(Name, &symbolId)); + + if (symbolId >> 31) + return E_INVALIDARG; + + const DxcHLSLNode &node = data.Nodes[symbolId]; + + if (node.GetNodeType() != DxcHLSLNodeType::Enum) + return E_INVALIDARG; + + return GetEnumValueByIndex(node.GetLocalId(), ValueIndex, pValueDesc); + } + + STDMETHOD(GetAnnotationCountByName) + (THIS_ _In_ LPCSTR SymbolName, _Out_ UINT *pCount) override { + + IFR(ZeroMemoryToOut(pCount)); + + UINT symbolId = UINT(-1); + IFR(GetSymbolByName(SymbolName, &symbolId)); + + if (symbolId >> 31) + return E_INVALIDARG; + + return GetAnnotationCount(symbolId, pCount); + } + + STDMETHOD(GetAnnotationByIndexAndName) + (THIS_ _In_ LPCSTR SymbolName, _In_ UINT Index, + _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) override { + + IFR(ZeroMemoryToOut(pAnnotation)); + + UINT symbolId = UINT(-1); + IFR(GetSymbolByName(SymbolName, &symbolId)); + + if (symbolId >> 31) + return E_INVALIDARG; + + return GetAnnotationByIndex(symbolId, Index, pAnnotation); + } + + STDMETHOD(GetFunctionDescByName) + (THIS_ _In_ LPCSTR Name, + THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) override{ + + IFR(ZeroMemoryToOut(pDesc)); + + UINT symbolId = UINT(-1); + IFR(GetSymbolByName(Name, &symbolId)); + + if (symbolId >> 31) + return E_INVALIDARG; + + const DxcHLSLNode &node = data.Nodes[symbolId]; + + if (node.GetNodeType() != DxcHLSLNodeType::Function) + return E_INVALIDARG; + + return GetFunctionDesc(node.GetLocalId(), pDesc); + } + + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByName) + (THIS_ _In_ LPCSTR Name) PURE; + + STDMETHOD(GetStructTypeByName) + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; +}; + +namespace { + +std::string DefinesToString(DxcDefine *pDefines, UINT32 defineCount) { + std::string defineStr; + for (UINT32 i = 0; i < defineCount; i++) { + CW2A utf8Name(pDefines[i].Name); + CW2A utf8Value(pDefines[i].Value); + defineStr += "#define "; + defineStr += utf8Name; + defineStr += " "; + defineStr += utf8Value ? utf8Value.m_psz : "1"; + defineStr += "\n"; + } + + return defineStr; +} + +void SetupCompilerCommon(CompilerInstance &compiler, + DxcLangExtensionsHelper *helper, LPCSTR pMainFile, + TextDiagnosticPrinter *diagPrinter, + ASTUnit::RemappedFile *rewrite, + hlsl::options::DxcOpts &opts) { + // Setup a compiler instance. + std::shared_ptr targetOptions(new TargetOptions); + targetOptions->Triple = llvm::sys::getDefaultTargetTriple(); + compiler.HlslLangExtensions = helper; + compiler.createDiagnostics(diagPrinter, false); + compiler.createFileManager(); + compiler.createSourceManager(compiler.getFileManager()); + compiler.setTarget( + TargetInfo::CreateTargetInfo(compiler.getDiagnostics(), targetOptions)); + // Not use builtin includes. + compiler.getHeaderSearchOpts().UseBuiltinIncludes = false; + + // apply compiler options applicable for rewrite + if (opts.WarningAsError) + compiler.getDiagnostics().setWarningsAsErrors(true); + compiler.getDiagnostics().setIgnoreAllWarnings(!opts.OutputWarnings); + compiler.getLangOpts().HLSLVersion = opts.HLSLVersion; + compiler.getLangOpts().PreserveUnknownAnnotations = + opts.RWOpt.ReflectHLSLBasics; + compiler.getLangOpts().UseMinPrecision = !opts.Enable16BitTypes; + compiler.getLangOpts().EnableDX9CompatMode = opts.EnableDX9CompatMode; + compiler.getLangOpts().EnableFXCCompatMode = opts.EnableFXCCompatMode; + compiler.getDiagnostics().setIgnoreAllWarnings(!opts.OutputWarnings); + compiler.getCodeGenOpts().MainFileName = pMainFile; + + PreprocessorOptions &PPOpts = compiler.getPreprocessorOpts(); + if (rewrite != nullptr) { + if (llvm::MemoryBuffer *pMemBuf = rewrite->second) { + compiler.getPreprocessorOpts().addRemappedFile(StringRef(pMainFile), + pMemBuf); + } + + PPOpts.RemappedFilesKeepOriginalName = true; + } + + PPOpts.ExpandTokPastingArg = opts.LegacyMacroExpansion; + + // Pick additional arguments. + clang::HeaderSearchOptions &HSOpts = compiler.getHeaderSearchOpts(); + HSOpts.UseBuiltinIncludes = 0; + // Consider: should we force-include '.' if the source file is relative? + for (const llvm::opt::Arg *A : opts.Args.filtered(options::OPT_I)) { + const bool IsFrameworkFalse = false; + const bool IgnoreSysRoot = true; + if (dxcutil::IsAbsoluteOrCurDirRelative(A->getValue())) { + HSOpts.AddPath(A->getValue(), frontend::Angled, IsFrameworkFalse, + IgnoreSysRoot); + } else { + std::string s("./"); + s += A->getValue(); + HSOpts.AddPath(s, frontend::Angled, IsFrameworkFalse, IgnoreSysRoot); + } + } +} + +void SetupCompiler(CompilerInstance &compiler, + DxcLangExtensionsHelper *helper, LPCSTR pMainFile, + TextDiagnosticPrinter *diagPrinter, + ASTUnit::RemappedFile *rewrite, + hlsl::options::DxcOpts &opts, LPCSTR pDefines, + dxcutil::DxcArgsFileSystem *msfPtr) { + + SetupCompilerCommon(compiler, helper, pMainFile, diagPrinter, rewrite, opts); + + if (msfPtr) { + msfPtr->SetupForCompilerInstance(compiler); + } + + compiler.createPreprocessor(TU_Complete); + + if (pDefines) { + std::string newDefines = compiler.getPreprocessor().getPredefines(); + newDefines += pDefines; + compiler.getPreprocessor().setPredefines(newDefines); + } + + compiler.createASTContext(); + compiler.setASTConsumer(std::unique_ptr(new SemaConsumer())); + compiler.createSema(TU_Complete, nullptr); + + const FileEntry *mainFileEntry = + compiler.getFileManager().getFile(StringRef(pMainFile)); + if (mainFileEntry == nullptr) { + throw ::hlsl::Exception(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); + } + compiler.getSourceManager().setMainFileID( + compiler.getSourceManager().createFileID(mainFileEntry, SourceLocation(), + SrcMgr::C_User)); +} + +HRESULT GenerateAST(DxcLangExtensionsHelper *pExtHelper, LPCSTR pFileName, + ASTUnit::RemappedFile *pRemap, DxcDefine *pDefines, + UINT32 defineCount, ASTHelper &astHelper, + hlsl::options::DxcOpts &opts, + dxcutil::DxcArgsFileSystem *msfPtr, raw_ostream &w) { + // Setup a compiler instance. + CompilerInstance &compiler = astHelper.compiler; + + std::unique_ptr diagPrinter = + llvm::make_unique(w, + &compiler.getDiagnosticOpts()); + std::string definesStr = DefinesToString(pDefines, defineCount); + + SetupCompiler( + compiler, pExtHelper, pFileName, diagPrinter.get(), pRemap, opts, + defineCount > 0 ? definesStr.c_str() : nullptr, msfPtr); + + // Parse the source file. + compiler.getDiagnosticClient().BeginSourceFile(compiler.getLangOpts(), + &compiler.getPreprocessor()); + + ParseAST(compiler.getSema(), false, opts.RWOpt.SkipFunctionBody); + + ASTContext &C = compiler.getASTContext(); + TranslationUnitDecl *tu = C.getTranslationUnitDecl(); + astHelper.tu = tu; + + if (compiler.getDiagnosticClient().getNumErrors() > 0) { + astHelper.bHasErrors = true; + w.flush(); + return E_FAIL; + } + astHelper.bHasErrors = false; + return S_OK; +} + +HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, + ASTUnit::RemappedFile *pRemap, + hlsl::options::DxcOpts &opts, DxcDefine *pDefines, + UINT32 defineCount, std::string &warnings, + std::string &result, + dxcutil::DxcArgsFileSystem *msfPtr, + DxcHLSLReflectionData &reflection) { + + raw_string_ostream o(result); + raw_string_ostream w(warnings); + + ASTHelper astHelper; + + HRESULT hr = GenerateAST(pHelper, pFileName, pRemap, pDefines, defineCount, astHelper, + opts, msfPtr, w); + + if (FAILED(hr)) + return hr; + + if (astHelper.bHasErrors) + return E_FAIL; + + TranslationUnitDecl *tu = astHelper.tu; + + D3D12_HLSL_REFLECTION_FEATURE reflectMask = + D3D12_HLSL_REFLECTION_FEATURE_NONE; + + if (opts.RWOpt.ReflectHLSLBasics) + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_BASICS; + + if (opts.RWOpt.ReflectHLSLFunctions) + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS; + + if (opts.RWOpt.ReflectHLSLNamespaces) + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES; + + if (opts.RWOpt.ReflectHLSLUserTypes) + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES; + + if (opts.RWOpt.ReflectHLSLScopes) + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SCOPES; + + if (opts.RWOpt.ReflectHLSLVariables) + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_VARIABLES; + + if (!opts.RWOpt.ReflectHLSLDisableSymbols) + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (!reflectMask) + reflectMask = D3D12_HLSL_REFLECTION_FEATURE_ALL; + + DxcHLSLReflectionData refl(astHelper.compiler, *astHelper.tu, + opts.AutoBindingSpace, reflectMask, + opts.DefaultRowMajor); + + //TODO: Debug + + refl.Printf(); + + // Test serialization + + std::vector bytes; + refl.Dump(bytes); + + DxcHLSLReflectionData deserialized(bytes, true); + + assert(deserialized == refl && "Dump or Deserialize doesn't match"); + + printf("Reflection size: %" PRIu64 "\n", bytes.size()); + + // Test stripping symbols + + refl.StripSymbols(); + refl.Printf(); + + refl.Dump(bytes); + + DxcHLSLReflectionData deserialized2 = DxcHLSLReflectionData(bytes, false); + + assert(deserialized2 == refl && "Dump or Deserialize doesn't match"); + + printf("Stripped reflection size: %" PRIu64 "\n", bytes.size()); + + reflection = std::move(deserialized); + + // Flush and return results. + o.flush(); + w.flush(); + + return S_OK; +} + +HRESULT ReadOptsAndValidate(hlsl::options::MainArgs &mainArgs, + hlsl::options::DxcOpts &opts, + IDxcOperationResult **ppResult) { + const llvm::opt::OptTable *table = ::options::getHlslOptTable(); + + CComPtr pOutputStream; + IFT(CreateMemoryStream(GetGlobalHeapMalloc(), &pOutputStream)); + raw_stream_ostream outStream(pOutputStream); + + if (0 != hlsl::options::ReadDxcOpts(table, + hlsl::options::HlslFlags::RewriteOption, + mainArgs, opts, outStream)) { + CComPtr pErrorBlob; + IFT(pOutputStream->QueryInterface(&pErrorBlob)); + outStream.flush(); + IFT(DxcResult::Create( + E_INVALIDARG, DXC_OUT_NONE, + {DxcOutputObject::ErrorOutput(opts.DefaultTextCodePage, + (LPCSTR)pErrorBlob->GetBufferPointer(), + pErrorBlob->GetBufferSize())}, + ppResult)); + return S_OK; + } + return S_OK; +} +} // namespace + +class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { +private: + DXC_MICROCOM_TM_REF_FIELDS() + DxcLangExtensionsHelper m_langExtensionsHelper; + +public: + DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL() + DXC_MICROCOM_TM_CTOR(DxcReflector) + DXC_LANGEXTENSIONS_HELPER_IMPL(m_langExtensionsHelper) + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, + void **ppvObject) override { + return DoBasicQueryInterface( + this, iid, ppvObject); + } + + HRESULT STDMETHODCALLTYPE FromSource( + IDxcBlobEncoding *pSource, + // Optional file name for pSource. Used in errors and include handlers. + LPCWSTR pSourceName, + // Compiler arguments + LPCWSTR *pArguments, UINT32 argCount, + // Defines + DxcDefine *pDefines, UINT32 defineCount, + // user-provided interface to handle #include directives (optional) + IDxcIncludeHandler *pIncludeHandler, + IDxcOperationResult **ppResult) override { + + if (pSource == nullptr || ppResult == nullptr || + (argCount > 0 && pArguments == nullptr) || + (defineCount > 0 && pDefines == nullptr)) + return E_POINTER; + + *ppResult = nullptr; + + DxcThreadMalloc TM(m_pMalloc); + + CComPtr utf8Source; + IFR(hlsl::DxcGetBlobAsUtf8(pSource, m_pMalloc, &utf8Source)); + + CW2A utf8SourceName(pSourceName); + LPCSTR fName = utf8SourceName.m_psz; + + try { + dxcutil::DxcArgsFileSystem *msfPtr = dxcutil::CreateDxcArgsFileSystem( + utf8Source, pSourceName, pIncludeHandler); + std::unique_ptr<::llvm::sys::fs::MSFileSystem> msf(msfPtr); + ::llvm::sys::fs::AutoPerThreadSystem pts(msf.get()); + IFTLLVM(pts.error_code()); + + hlsl::options::MainArgs mainArgs(argCount, pArguments, 0); + + hlsl::options::DxcOpts opts; + IFR(ReadOptsAndValidate(mainArgs, opts, ppResult)); + HRESULT hr; + if (*ppResult && SUCCEEDED((*ppResult)->GetStatus(&hr)) && FAILED(hr)) { + // Looks odd, but this call succeeded enough to allocate a result + return S_OK; + } + + StringRef Data(utf8Source->GetStringPointer(), + utf8Source->GetStringLength()); + std::unique_ptr pBuffer( + llvm::MemoryBuffer::getMemBufferCopy(Data, fName)); + std::unique_ptr pRemap( + new ASTUnit::RemappedFile(fName, pBuffer.release())); + + DxcHLSLReflectionData reflection; + + std::string errors; + std::string rewrite; + HRESULT status = GetFromSource(&m_langExtensionsHelper, fName, + pRemap.get(), opts, pDefines, defineCount, + errors, rewrite, msfPtr, reflection); + + std::vector Bytes; + + if (SUCCEEDED(status)) + reflection.Dump(Bytes); + + return DxcResult::Create( + status, DXC_OUT_OBJECT, + {DxcOutputObject::ObjectOutput(Bytes.data(), Bytes.size()), + DxcOutputObject::ErrorOutput(opts.DefaultTextCodePage, + errors.c_str())}, + ppResult); + } + CATCH_CPP_RETURN_HRESULT(); + } + + //TODO: + + HRESULT STDMETHODCALLTYPE FromBlob(IDxcBlob *data, IDxcHLSLReflection **ppReflection) override { + + if (!data || !data->GetBufferSize() || !ppReflection) + return E_POINTER; + + /* TODO: */ + + return E_FAIL; + } + + HRESULT STDMETHODCALLTYPE ToBlob(IDxcHLSLReflection *reflection, + IDxcBlob **ppResult) override { + + if (!reflection || !ppResult) + return E_POINTER; + + /*TODO: + DxcHLSLReflection *refl = ...; + + std::vector bytes; + refl->data.Dump(bytes); + + library->CreateBlobWithEncodingOnHeapCopy( + vec.data(), // pointer to your data + static_cast(vec.size()), // size in bytes + CP_UTF8, // or 0 for "unknown" + &blob); + */ + + return E_FAIL; + } +}; + +HRESULT CreateDxcReflector(REFIID riid, LPVOID *ppv) { + CComPtr isense = DxcReflector::Alloc(DxcGetThreadMallocNoRef()); + IFROOM(isense.p); + return isense.p->QueryInterface(riid, ppv); +} \ No newline at end of file diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 20e1b49d4a..8a13c8c1b2 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1097,7 +1097,7 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, //Reflect - DxcHLSLReflection refl(astHelper.compiler, *astHelper.tu, + DxcHLSLReflectionData refl(astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, reflectMask, opts.DefaultRowMajor); @@ -1108,7 +1108,7 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, std::vector bytes; refl.Dump(bytes); - DxcHLSLReflection deserialized(bytes, true); + DxcHLSLReflectionData deserialized(bytes, true); assert(deserialized == refl && "Dump or Deserialize doesn't match"); @@ -1121,7 +1121,7 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, refl.Dump(bytes); - deserialized = DxcHLSLReflection(bytes, false); + deserialized = DxcHLSLReflectionData(bytes, false); assert(deserialized == refl && "Dump or Deserialize doesn't match"); From 11ec78beeeb20e95f4292a0ed48392d4db5b354f Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 9 Sep 2025 22:19:40 +0200 Subject: [PATCH 029/126] Added a node API to IDxcHLSLReflection to allow querying symbols as well as a non recursive child count. TODO: Structs, function parameters, constant buffers, types, arrays. --- include/dxc/DxcReflection/DxcReflection.h | 26 +- include/dxc/dxctools.h | 74 +++++- .../tools/dxcreflection/DxcReflection.cpp | 93 +++---- tools/clang/tools/libclang/dxcreflector.cpp | 240 +++++++++++------- 4 files changed, 266 insertions(+), 167 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 29fb0f33b0..23f1181870 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -25,22 +25,6 @@ class CompilerInstance; #pragma warning(disable : 4201) namespace hlsl { - -enum class DxcHLSLNodeType : uint64_t { - - Register, - Function, - Enum, - EnumValue, - Namespace, - Typedef, - Using, - Variable, //localId points to the type for a variable - //Parameter, - - Start = Register, - End = Variable -}; struct DxcHLSLNode { @@ -78,8 +62,8 @@ struct DxcHLSLNode { uint32_t GetLocalId() const { return LocalIdParentLo << 8 >> 8; } uint32_t GetAnnotationStart() const { return AnnotationStartPad; } - DxcHLSLNodeType GetNodeType() const { - return DxcHLSLNodeType(ParentHiAnnotationsType >> 26); + D3D12_HLSL_NODE_TYPE GetNodeType() const { + return D3D12_HLSL_NODE_TYPE(ParentHiAnnotationsType >> 26); } // Includes recursive children @@ -111,7 +95,7 @@ struct DxcHLSLNodeSymbol { struct { uint32_t NameId; // Local name (not including parent's name) - uint16_t FileNameId; //-1 == no file info + uint16_t FileSourceId; //-1 == no file info uint16_t SourceLineCount; }; uint64_t NameIdFileNameIdSourceLineCount; @@ -128,10 +112,10 @@ struct DxcHLSLNodeSymbol { DxcHLSLNodeSymbol() = default; - DxcHLSLNodeSymbol(uint32_t NameId, uint16_t FileNameId, + DxcHLSLNodeSymbol(uint32_t NameId, uint16_t FileSourceId, uint16_t SourceLineCount, uint32_t SourceLineStart, uint32_t SourceColumnStart, uint32_t SourceColumnEnd) - : NameId(NameId), FileNameId(FileNameId), + : NameId(NameId), FileSourceId(FileSourceId), SourceLineCount(SourceLineCount), SourceColumnStartLo(uint16_t(SourceColumnStart)), SourceColumnEndLo(uint16_t(SourceColumnEnd)), diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 5434ee32d8..5e2f92a046 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -164,6 +164,39 @@ struct D3D12_HLSL_ANNOTATION { BOOL IsBuiltin; }; +enum D3D12_HLSL_NODE_TYPE { + + D3D12_HLSL_NODE_TYPE_REGISTER, + D3D12_HLSL_NODE_TYPE_FUNCTION, + D3D12_HLSL_NODE_TYPE_ENUM, + D3D12_HLSL_NODE_TYPE_ENUM_VALUE, + D3D12_HLSL_NODE_TYPE_NAMESPACE, + D3D12_HLSL_NODE_TYPE_VARIABLE, // LocalId points to the type for a variable + //D3D12_HLSL_NODE_TYPE_TYPEDEF, + //D3D12_HLSL_NODE_TYPE_USING, + // TODO: Parameter, + + D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_VARIABLE +}; + +struct D3D12_HLSL_NODE { + LPCSTR Name; + D3D12_HLSL_NODE_TYPE Type; + UINT LocalId; + UINT ChildCount; + UINT Parent; + UINT AnnotationCount; +}; + +struct D3D12_HLSL_NODE_SYMBOL { + LPCSTR FileName; + UINT LineId; + UINT LineCount; + UINT ColumnStart; + UINT ColumnEnd; +}; + typedef interface ID3D12ShaderReflectionConstantBuffer ID3D12ShaderReflectionConstantBuffer; @@ -191,7 +224,7 @@ DECLARE_INTERFACE(IDxcHLSLReflection) { // The D3D12_SHADER_INPUT_BIND_DESC permits providing invalid Space and // BindPoint. In the future, implementations could decide to return this - // depending on the backend. But since this is a HLSL frontend thing, we don't + // depending on the backend. But since this is HLSL frontend reflection, we don't // know the bindings on the backend. STDMETHOD(GetResourceBindingDesc) @@ -217,27 +250,40 @@ DECLARE_INTERFACE(IDxcHLSLReflection) { (THIS_ _In_ UINT EnumIndex, _In_ UINT ValueIndex, _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) PURE; - STDMETHOD(GetAnnotationCount) - (THIS_ _In_ UINT SymbolId, _Out_ UINT *pCount) PURE; - STDMETHOD(GetAnnotationByIndex) - (THIS_ _In_ UINT SymbolId, _In_ UINT Index, + (THIS_ _In_ UINT NodeId, _In_ UINT Index, _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) PURE; - // Name helpers; only available if symbols aren't stripped + STDMETHOD(GetNodeDesc) + (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE *pDesc) PURE; + + STDMETHOD(GetChildNode) + (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, + _Out_ UINT *pChildNodeId) PURE; + + STDMETHOD(GetChildDesc) + (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, + _Out_ D3D12_HLSL_NODE *pDesc) PURE; + + // Only available if symbols aren't stripped - STDMETHOD(GetSymbolByName) - (THIS_ _In_ LPCSTR Name, _Out_ UINT *pSymbolId) PURE; + STDMETHOD(GetNodeSymbolDesc) + (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE_SYMBOL *pSymbol) PURE; - STDMETHOD(GetSymbolName) - (THIS_ _In_ UINT SymbolId, _Out_ LPCSTR *pSymbolName) PURE; + // Name helpers - STDMETHOD(GetAnnotationCountByName) - (THIS_ _In_ LPCSTR SymbolName, _Out_ UINT *pCount) PURE; + STDMETHOD(GetNodeByName) + (THIS_ _In_ LPCSTR Name, _Out_ UINT *pNodeId) PURE; + + STDMETHOD(GetNodeSymbolDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE_SYMBOL *pSymbol) PURE; + + STDMETHOD(GetNodeDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE *pDesc) PURE; STDMETHOD(GetAnnotationByIndexAndName) - (THIS_ _In_ LPCSTR SymbolName, _In_ UINT Index, - _Out_ D3D12_HLSL_ANNOTATION *ppAnnotationText) PURE; + (THIS_ _In_ LPCSTR Name, _In_ UINT Index, + _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) PURE; STDMETHOD(GetEnumDescByName) (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index cdf0f76c33..16fc089895 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -68,7 +68,7 @@ static uint32_t RegisterString(DxcHLSLReflectionData &Refl, static uint32_t PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, const LangOptions &LangOpts, const std::string &UnqualifiedName, Decl *Decl, - DxcHLSLNodeType Type, uint32_t ParentNodeId, + D3D12_HLSL_NODE_TYPE Type, uint32_t ParentNodeId, uint32_t LocalId, const SourceRange *Range = nullptr) { assert(Refl.Nodes.size() < (uint32_t)(1 << 24) && "Nodes overflow"); @@ -117,7 +117,7 @@ static uint32_t PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager uint32_t sourceColumnStart = 0; uint32_t sourceColumnEnd = 0; - uint16_t fileNameId = (uint16_t)-1; + uint16_t sourceId = (uint16_t)-1; SourceRange range = Decl ? Decl->getSourceRange() : (Range ? *Range : SourceRange()); @@ -170,14 +170,14 @@ static uint32_t PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager sourceLineStart = startLine; sourceColumnStart = startCol; sourceColumnEnd = endCol; - fileNameId = (uint16_t)i; + sourceId = (uint16_t)i; } } uint32_t nameId = RegisterString(Refl, UnqualifiedName, false); Refl.NodeSymbols.push_back( - DxcHLSLNodeSymbol(nameId, fileNameId, sourceLineCount, sourceLineStart, + DxcHLSLNodeSymbol(nameId, sourceId, sourceLineCount, sourceLineStart, sourceColumnStart, sourceColumnEnd)); } @@ -808,8 +808,8 @@ static void FillReflectionRegisterAt( DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, - DxcHLSLNodeType::Register, ParentNodeId, (uint32_t)Refl.Registers.size()); + Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, + (uint32_t)Refl.Registers.size()); uint32_t arrayId = PushArray(Refl, ArraySizeFlat, ArraySize); @@ -875,7 +875,7 @@ static void FillReflectionRegisterAt( PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), isListType ? "$Element" : ValDesc->getName(), nullptr, - DxcHLSLNodeType::Variable, nodeId, typeId, &sourceRange); + D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, typeId, &sourceRange); break; } @@ -911,7 +911,7 @@ void RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, decl, - DxcHLSLNodeType::Variable, ParentId, typeId); + D3D12_HLSL_NODE_TYPE_VARIABLE, ParentId, typeId); //Handle struct recursion @@ -961,7 +961,7 @@ static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, Refl, SM, ASTCtx.getLangOpts(), Decl && dyn_cast(Decl) ? dyn_cast(Decl)->getName() : "", - Decl, DxcHLSLNodeType::Parameter, ParentNodeId, + Decl, D3D12_HLSL_NODE_TYPE_PARAMETER, ParentNodeId, (uint32_t)Refl.Parameters.size()); std::string semanticName; @@ -1032,7 +1032,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), CBuffer->getName(), - CBuffer, DxcHLSLNodeType::Register, ParentNodeId, + CBuffer, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, (uint32_t)Refl.Registers.size()); uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, SM, CBuffer, nodeId, @@ -1060,7 +1060,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), Func->getName(), Func, - DxcHLSLNodeType::Function, ParentNodeId, + D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, (uint32_t)Refl.Functions.size()); bool hasDefinition = Func->hasBody(Definition); @@ -1109,13 +1109,13 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, uint32_t nodeId = PushNextNodeId( Refl, SM, ASTCtx.getLangOpts(), Enum->getName(), Enum, - DxcHLSLNodeType::Enum, ParentNodeId, (uint32_t)Refl.Enums.size()); + D3D12_HLSL_NODE_TYPE_ENUM, ParentNodeId, (uint32_t)Refl.Enums.size()); for (EnumConstantDecl *EnumValue : Enum->enumerators()) { uint32_t childNodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), EnumValue->getName(), - EnumValue, DxcHLSLNodeType::EnumValue, nodeId, + EnumValue, D3D12_HLSL_NODE_TYPE_ENUM_VALUE, nodeId, (uint32_t)Refl.EnumValues.size()); Refl.EnumValues.push_back( @@ -1206,7 +1206,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, uint32_t nodeId = PushNextNodeId( Refl, SM, ASTCtx.getLangOpts(), Namespace->getName(), Namespace, - DxcHLSLNodeType::Namespace, ParentNodeId, 0); + D3D12_HLSL_NODE_TYPE_NAMESPACE, ParentNodeId, 0); RecursiveReflectHLSL(*Namespace, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, nodeId, @@ -1234,7 +1234,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(clang::CompilerInstance &Compiler, } Nodes.push_back( - DxcHLSLNode{DxcHLSLNodeType::Namespace, 0, 0, 0, 0xFFFF, 0}); + DxcHLSLNode{D3D12_HLSL_NODE_TYPE_NAMESPACE, 0, 0, 0, 0xFFFF, 0}); RecursiveReflectHLSL(Ctx, Compiler.getASTContext(), Diags, SM, *this, AutoBindingSpace, 0, Features, 0, DefaultRowMaj); @@ -1267,10 +1267,10 @@ static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { return arr[type]; } -static std::string NodeTypeToString(DxcHLSLNodeType type) { +static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { static const char *arr[] = {"Register", "Function", "Enum", "EnumValue", - "Namespace", "Typedef", "Using", "Variable"}; + "Namespace", "Variable"}; return arr[(int)type]; } @@ -1461,7 +1461,7 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, switch (node.GetNodeType()) { - case DxcHLSLNodeType::Register: { + case D3D12_HLSL_NODE_TYPE_REGISTER: { const DxcHLSLRegister ® = Refl.Registers[localId]; @@ -1474,11 +1474,11 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, break; } - case DxcHLSLNodeType::Variable: + case D3D12_HLSL_NODE_TYPE_VARIABLE: typeToPrint = localId; break; - case DxcHLSLNodeType::Function: { + case D3D12_HLSL_NODE_TYPE_FUNCTION: { const DxcHLSLFunction &func = Refl.Functions[localId]; printf("%sreturn: %s, hasDefinition: %s, numParams: %u\n", std::string(Depth, '\t').c_str(), @@ -1488,23 +1488,23 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, break; } - case DxcHLSLNodeType::Enum: + case D3D12_HLSL_NODE_TYPE_ENUM: printf("%s: %s\n", std::string(Depth, '\t').c_str(), EnumTypeToString(Refl.Enums[localId].Type).c_str()); break; - case DxcHLSLNodeType::EnumValue: { + case D3D12_HLSL_NODE_TYPE_ENUM_VALUE: { printf("%s#%u = %" PRIi64 "\n", std::string(Depth, '\t').c_str(), IndexInParent, Refl.EnumValues[localId].Value); break; } //TODO: - case DxcHLSLNodeType::Typedef: - case DxcHLSLNodeType::Using: - break; + //case D3D12_HLSL_NODE_TYPE_TYPEDEF: + //case D3D12_HLSL_NODE_TYPE_USING: + // break; - case DxcHLSLNodeType::Namespace: + case D3D12_HLSL_NODE_TYPE_NAMESPACE: default: break; } @@ -1750,8 +1750,8 @@ uint32_t RecurseNameGeneration(DxcHLSLReflectionData &Refl, uint32_t NodeId, Refl.FullyResolvedToNodeId[self] = NodeId; Refl.NodeIdToFullyResolved[NodeId] = self; - bool isDotChild = node.GetNodeType() == DxcHLSLNodeType::Register; - bool isVar = node.GetNodeType() == DxcHLSLNodeType::Variable; + bool isDotChild = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_REGISTER; + bool isVar = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_VARIABLE; for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) i += RecurseNameGeneration(Refl, NodeId + 1 + i, j, self, isDotChild); @@ -1866,14 +1866,14 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLNode &node = Nodes[i]; if (hasSymbolInfo && (NodeSymbols[i].NameId >= header.Strings || - (NodeSymbols[i].FileNameId != uint16_t(-1) && - NodeSymbols[i].FileNameId >= header.Sources))) + (NodeSymbols[i].FileSourceId != uint16_t(-1) && + NodeSymbols[i].FileSourceId >= header.Sources))) throw std::invalid_argument("Node " + std::to_string(i) + " points to invalid name or file name"); if( node.GetAnnotationStart() + node.GetAnnotationCount() > header.Annotations || - node.GetNodeType() > DxcHLSLNodeType::End || + node.GetNodeType() > D3D12_HLSL_NODE_TYPE_END || (i && node.GetParentId() >= i) || i + node.GetChildCount() > header.Nodes ) @@ -1882,21 +1882,22 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes uint32_t maxValue = 1; switch(node.GetNodeType()) { - case DxcHLSLNodeType::Register: + case D3D12_HLSL_NODE_TYPE_REGISTER: maxValue = header.Registers; break; - case DxcHLSLNodeType::Function: + case D3D12_HLSL_NODE_TYPE_FUNCTION: maxValue = header.Functions; break; - case DxcHLSLNodeType::Enum: + case D3D12_HLSL_NODE_TYPE_ENUM: maxValue = header.Enums; break; - case DxcHLSLNodeType::EnumValue: + case D3D12_HLSL_NODE_TYPE_ENUM_VALUE: maxValue = header.EnumValues; break; - case DxcHLSLNodeType::Typedef: - case DxcHLSLNodeType::Using: - case DxcHLSLNodeType::Variable: + //TODO: + //case D3D12_HLSL_NODE_TYPE_TYPEDEF: + //case D3D12_HLSL_NODE_TYPE_USING: + case D3D12_HLSL_NODE_TYPE_VARIABLE: maxValue = header.Types; break; } @@ -1911,7 +1912,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if( reg.NodeId >= header.Nodes || - Nodes[reg.NodeId].GetNodeType() != DxcHLSLNodeType::Register || + Nodes[reg.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER || Nodes[reg.NodeId].GetLocalId() != i ) throw std::invalid_argument("Register " + std::to_string(i) + " points to an invalid nodeId"); @@ -1942,7 +1943,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLFunction &func = Functions[i]; if (func.NodeId >= header.Nodes || - Nodes[func.NodeId].GetNodeType() != DxcHLSLNodeType::Function || + Nodes[func.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION || Nodes[func.NodeId].GetLocalId() != i) throw std::invalid_argument("Function " + std::to_string(i) + " points to an invalid nodeId"); @@ -1953,7 +1954,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLEnumDesc &enm = Enums[i]; if (enm.NodeId >= header.Nodes || - Nodes[enm.NodeId].GetNodeType() != DxcHLSLNodeType::Enum || + Nodes[enm.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM || Nodes[enm.NodeId].GetLocalId() != i) throw std::invalid_argument("Function " + std::to_string(i) + " points to an invalid nodeId"); @@ -1970,7 +1971,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLNode &child = Nodes[enm.NodeId + 1 + j]; if (child.GetChildCount() != 0 || - child.GetNodeType() != DxcHLSLNodeType::EnumValue) + child.GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM_VALUE) throw std::invalid_argument("Enum " + std::to_string(i) + " has an invalid enum value"); } @@ -1981,10 +1982,10 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLEnumValue &enumVal = EnumValues[i]; if (enumVal.NodeId >= header.Nodes || - Nodes[enumVal.NodeId].GetNodeType() != DxcHLSLNodeType::EnumValue || + Nodes[enumVal.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM_VALUE || Nodes[enumVal.NodeId].GetLocalId() != i || Nodes[Nodes[enumVal.NodeId].GetParentId()].GetNodeType() != - DxcHLSLNodeType::Enum) + D3D12_HLSL_NODE_TYPE_ENUM) throw std::invalid_argument("Enum " + std::to_string(i) + " points to an invalid nodeId"); } @@ -2009,7 +2010,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLBuffer &buf = Buffers[i]; if (buf.NodeId >= header.Nodes || - Nodes[buf.NodeId].GetNodeType() != DxcHLSLNodeType::Register || + Nodes[buf.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER || Nodes[buf.NodeId].GetLocalId() >= header.Registers || Registers[Nodes[buf.NodeId].GetLocalId()].BufferId != i) throw std::invalid_argument("Buffer " + std::to_string(i) + @@ -2026,7 +2027,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLNode &child = Nodes[buf.NodeId + 1 + j]; if (child.GetChildCount() != 0 || - child.GetNodeType() != DxcHLSLNodeType::Variable) + child.GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) throw std::invalid_argument("Buffer " + std::to_string(i) + " has to have only Variable child nodes"); } diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 0a660eb10d..fd7ca26a95 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -60,15 +60,39 @@ struct ASTHelper { struct DxcHLSLReflection : public IDxcHLSLReflection { DxcHLSLReflectionData data{}; + std::vector childCountsNonRecursive; + std::unordered_map> childrenNonRecursive; DxcHLSLReflection() = default; - DxcHLSLReflection(DxcHLSLReflectionData &&moved) : data(moved) { + + void Finalize() { + data.GenerateNameLookupTable(); + + childCountsNonRecursive.resize(data.Nodes.size()); + childrenNonRecursive.clear(); + + for (uint32_t i = 0; i < (uint32_t)data.Nodes.size(); ++i) { + + const DxcHLSLNode &node = data.Nodes[i]; + uint32_t childCount = 0; + + for (uint32_t j = 0; j < node.GetChildCount(); ++j, ++childCount) { + childrenNonRecursive[i].push_back(i + 1 + j); + j += data.Nodes[i + 1 + j].GetChildCount(); + } + + childCountsNonRecursive[i] = childCount; + } + } + + DxcHLSLReflection(DxcHLSLReflectionData &&moved) : data(moved) { + Finalize(); } DxcHLSLReflection &operator=(DxcHLSLReflection &&moved) { data = std::move(moved.data); - data.GenerateNameLookupTable(); + Finalize(); return *this; } @@ -171,28 +195,16 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { return S_OK; } - STDMETHOD(GetAnnotationCount) - (THIS_ _In_ UINT SymbolId, _Out_ UINT *pCount) override { - - IFR(ZeroMemoryToOut(pCount)); - - if (SymbolId >= data.Nodes.size()) - return E_INVALIDARG; - - *pCount = data.Nodes[SymbolId].GetAnnotationCount(); - return S_OK; - } - STDMETHOD(GetAnnotationByIndex) - (THIS_ _In_ UINT SymbolId, _In_ UINT Index, + (THIS_ _In_ UINT NodeId, _In_ UINT Index, _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) override { IFR(ZeroMemoryToOut(pAnnotation)); - if (SymbolId >= data.Nodes.size()) + if (NodeId >= data.Nodes.size()) return E_INVALIDARG; - const DxcHLSLNode &node = data.Nodes[SymbolId]; + const DxcHLSLNode &node = data.Nodes[NodeId]; if (Index >= node.GetAnnotationCount()) return E_INVALIDARG; @@ -229,6 +241,61 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { return S_OK; } + STDMETHOD(GetNodeDesc) + (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + if (NodeId >= data.Nodes.size()) + return E_INVALIDARG; + + LPCSTR name = + data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + ? data.Strings[data.NodeSymbols[NodeId].NameId].c_str() + : ""; + + const DxcHLSLNode &node = data.Nodes[NodeId]; + + *pDesc = D3D12_HLSL_NODE{name, + node.GetNodeType(), + node.GetLocalId(), + childCountsNonRecursive[NodeId], + node.GetParentId(), + node.GetAnnotationCount()}; + + return S_OK; + } + + STDMETHOD(GetChildNode) + (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, + _Out_ UINT *pChildNodeId) override { + + IFR(ZeroMemoryToOut(pChildNodeId)); + + if (NodeId >= data.Nodes.size()) + return E_INVALIDARG; + + auto it = childrenNonRecursive.find(NodeId); + + if (it == childrenNonRecursive.end() || ChildId >= it->second.size()) + return E_INVALIDARG; + + *pChildNodeId = it->second[ChildId]; + return S_OK; + } + + STDMETHOD(GetChildDesc) + (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, + _Out_ D3D12_HLSL_NODE *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + uint32_t childNodeId; + IFR(GetChildNode(NodeId, ChildId, &childNodeId)); + + return GetNodeDesc(childNodeId, pDesc); + } + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex) (THIS_ _In_ UINT Index) PURE; @@ -239,45 +306,75 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { STDMETHOD(GetStructTypeByIndex) (THIS_ _In_ UINT StructIndex, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + + STDMETHOD(GetNodeSymbolDesc) + (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE_SYMBOL *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + if (!(data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO)) + return E_UNEXPECTED; + + if (NodeId >= data.Nodes.size()) + return E_INVALIDARG; + + const DxcHLSLNodeSymbol &nodeSymbol = data.NodeSymbols[NodeId]; + + *pDesc = D3D12_HLSL_NODE_SYMBOL{ + data.Strings[data.Sources[nodeSymbol.FileSourceId]].c_str(), + nodeSymbol.GetSourceLineStart(), nodeSymbol.SourceLineCount, + nodeSymbol.GetSourceColumnStart(), nodeSymbol.GetSourceColumnEnd()}; + + return S_OK; + } //Helper for conversion between symbol names - // TODO: GetSymbolByName // TODO: GetConstantBufferByIndex // TODO: GetConstantBufferByName // TODO: GetFunctionParameter // TODO: GetStructByIndex // TODO: GetStructTypeByName // TODO: GetStructTypeByIndex - // TODO: Node api, types, arrays + // TODO: types, arrays - STDMETHOD(GetSymbolByName) - (THIS_ _In_ LPCSTR Name, _Out_ UINT *pSymbolId) override; //TODO: 1st bit: isMember, else + STDMETHOD(GetNodeByName) + (THIS_ _In_ LPCSTR Name, _Out_ UINT *pNodeId) override { - STDMETHOD(GetSymbolName) - (THIS_ _In_ UINT SymbolId, _Out_ LPCSTR *pSymbolName) override { + if (!pNodeId) + return E_POINTER; - IFR(ZeroMemoryToOut(pSymbolName)); + *pNodeId = (UINT)-1; - if (!(data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO)) - return E_UNEXPECTED; + auto it = data.FullyResolvedToNodeId.find(Name); - if (SymbolId >> 31) { + if (it == data.FullyResolvedToNodeId.end()) + return E_INVALIDARG; - SymbolId = SymbolId << 1 >> 1; + *pNodeId = it->second; + return S_OK; + } - if (SymbolId >= data.MemberNameIds.size()) - return E_INVALIDARG; + STDMETHOD(GetNodeDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE *pDesc) override { - *pSymbolName = data.Strings[data.MemberNameIds[SymbolId]].c_str(); - return S_OK; - } + IFR(ZeroMemoryToOut(pDesc)); - if (SymbolId >= data.NodeSymbols.size()) - return E_INVALIDARG; + UINT nodeId; + IFR(GetNodeByName(Name, &nodeId)); - *pSymbolName = data.Strings[data.NodeSymbols[SymbolId].NameId].c_str(); - return S_OK; + return GetNodeDesc(nodeId, pDesc); + } + + STDMETHOD(GetNodeSymbolDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE_SYMBOL *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + UINT nodeId; + IFR(GetNodeByName(Name, &nodeId)); + + return GetNodeSymbolDesc(nodeId, pDesc); } STDMETHOD(GetResourceBindingDescByName) @@ -285,15 +382,12 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pDesc)); - UINT symbolId = UINT(-1); - IFR(GetSymbolByName(Name, &symbolId)); - - if (symbolId >> 31) - return E_INVALIDARG; + UINT nodeId; + IFR(GetNodeByName(Name, &nodeId)); - const DxcHLSLNode &node = data.Nodes[symbolId]; + const DxcHLSLNode &node = data.Nodes[nodeId]; - if (node.GetNodeType() != DxcHLSLNodeType::Register) + if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER) return E_INVALIDARG; return GetResourceBindingDesc(node.GetLocalId(), pDesc); @@ -304,15 +398,12 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pDesc)); - UINT symbolId = UINT(-1); - IFR(GetSymbolByName(Name, &symbolId)); + UINT nodeId; + IFR(GetNodeByName(Name, &nodeId)); - if (symbolId >> 31) - return E_INVALIDARG; - - const DxcHLSLNode &node = data.Nodes[symbolId]; + const DxcHLSLNode &node = data.Nodes[nodeId]; - if (node.GetNodeType() != DxcHLSLNodeType::Enum) + if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM) return E_INVALIDARG; return GetEnumDesc(node.GetLocalId(), pDesc); @@ -324,47 +415,27 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pValueDesc)); - UINT symbolId = UINT(-1); - IFR(GetSymbolByName(Name, &symbolId)); - - if (symbolId >> 31) - return E_INVALIDARG; + UINT nodeId; + IFR(GetNodeByName(Name, &nodeId)); - const DxcHLSLNode &node = data.Nodes[symbolId]; + const DxcHLSLNode &node = data.Nodes[nodeId]; - if (node.GetNodeType() != DxcHLSLNodeType::Enum) + if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM) return E_INVALIDARG; return GetEnumValueByIndex(node.GetLocalId(), ValueIndex, pValueDesc); } - STDMETHOD(GetAnnotationCountByName) - (THIS_ _In_ LPCSTR SymbolName, _Out_ UINT *pCount) override { - - IFR(ZeroMemoryToOut(pCount)); - - UINT symbolId = UINT(-1); - IFR(GetSymbolByName(SymbolName, &symbolId)); - - if (symbolId >> 31) - return E_INVALIDARG; - - return GetAnnotationCount(symbolId, pCount); - } - STDMETHOD(GetAnnotationByIndexAndName) - (THIS_ _In_ LPCSTR SymbolName, _In_ UINT Index, + (THIS_ _In_ LPCSTR Name, _In_ UINT Index, _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) override { IFR(ZeroMemoryToOut(pAnnotation)); - UINT symbolId = UINT(-1); - IFR(GetSymbolByName(SymbolName, &symbolId)); - - if (symbolId >> 31) - return E_INVALIDARG; + UINT nodeId; + IFR(GetNodeByName(Name, &nodeId)); - return GetAnnotationByIndex(symbolId, Index, pAnnotation); + return GetAnnotationByIndex(nodeId, Index, pAnnotation); } STDMETHOD(GetFunctionDescByName) @@ -373,15 +444,12 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pDesc)); - UINT symbolId = UINT(-1); - IFR(GetSymbolByName(Name, &symbolId)); - - if (symbolId >> 31) - return E_INVALIDARG; + UINT nodeId; + IFR(GetNodeByName(Name, &nodeId)); - const DxcHLSLNode &node = data.Nodes[symbolId]; + const DxcHLSLNode &node = data.Nodes[nodeId]; - if (node.GetNodeType() != DxcHLSLNodeType::Function) + if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION) return E_INVALIDARG; return GetFunctionDesc(node.GetLocalId(), pDesc); From c415cb2e607303d42600d1c6b8ef4ea15f77cf72 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 9 Sep 2025 22:24:00 +0200 Subject: [PATCH 030/126] Fixed some issues with building --- include/dxc/DxcReflection/DxcReflection.h | 6 +++--- include/dxc/dxctools.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 23f1181870..156c86d413 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -35,7 +35,7 @@ struct DxcHLSLNode { DxcHLSLNode() = default; - DxcHLSLNode(DxcHLSLNodeType NodeType, uint32_t LocalId, + DxcHLSLNode(D3D12_HLSL_NODE_TYPE NodeType, uint32_t LocalId, uint32_t AnnotationStart, uint32_t ChildCount, uint32_t ParentId, uint16_t AnnotationCount) : LocalIdParentLo(LocalId | (ParentId << 24)), @@ -46,8 +46,8 @@ struct DxcHLSLNode { (uint32_t(AnnotationCount) << 16) | (ParentId >> 8)) { - assert(NodeType >= DxcHLSLNodeType::Start && - NodeType <= DxcHLSLNodeType::End && "Invalid enum value"); + assert(NodeType >= D3D12_HLSL_NODE_TYPE_START && + NodeType <= D3D12_HLSL_NODE_TYPE_END && "Invalid enum value"); assert(LocalId < ((1 << 24) - 1) && "LocalId out of bounds"); assert(ParentId < ((1 << 24) - 1) && "ParentId out of bounds"); diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 5e2f92a046..70611a4c56 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -209,7 +209,7 @@ typedef interface IDxcHLSLReflection IDxcHLSLReflection; // {7016F834-AE85-4C86-A473-8C2C981DD370} interface DECLSPEC_UUID("7016f834-ae85-4c86-a473-8c2c981dd370") IDxcHLSLReflection; -DEFINE_GUID(IID_IDxcHLSLReflection, 0x7016f834, 0xae85, 0x4c86, 0xa473, 0x8c, +DEFINE_GUID(IID_IDxcHLSLReflection, 0x7016f834, 0xae85, 0x4c86, 0xa4, 0x73, 0x8c, 0x2c, 0x98, 0x1d, 0xd3, 0x70); #undef INTERFACE From 25a2000d8533d2a6204fb9be429e68b2c1a9ad01 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 17 Sep 2025 14:56:53 +0200 Subject: [PATCH 031/126] A node can now actually break the DAG, you can now point between the definition and declaration. These have strict rules and should be cautiously walked to avoid circular dependencies (though forward declares do solve a lot there too). Source column start/end is now longer. Removed some unused feature flags until they are properly supported. Added support for typedefs, structs and unions. Started an API to query types from the frontend. Fixed defining types with the same data but another name. Implemented 'constant buffer' (really it's just a buffer layout) from name/id in the frontend. TODO: Fix fwd declares of functions inside structs, namespaces (basically anything outside of the current namespace/struct/union/etc.). The idea will be to hide these nodes but still keep them somewhere, they can be found indirectly through the fwd declare but will be hidden from the scope they're defined in. --- include/dxc/DxcReflection/DxcReflection.h | 172 +++-- include/dxc/config.h | 4 + include/dxc/dxctools.h | 56 +- .../tools/dxcreflection/DxcReflection.cpp | 429 +++++++--- tools/clang/tools/libclang/dxcreflector.cpp | 730 +++++++++++++++--- .../clang/tools/libclang/dxcrewriteunused.cpp | 11 +- 6 files changed, 1111 insertions(+), 291 deletions(-) create mode 100644 include/dxc/config.h diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 156c86d413..435e2fa66c 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -26,25 +26,46 @@ class CompilerInstance; namespace hlsl { -struct DxcHLSLNode { +class DxcHLSLNode { uint32_t LocalIdParentLo; //24 : 8 - uint32_t ParentHiAnnotationsType; //16 : 10 : 6 - uint32_t ChildCountPad; //24 : 8 - uint32_t AnnotationStartPad; //20 : 12 + + union { + uint32_t ParentHiAnnotationsType32; + struct { + uint16_t ParentHi; + uint8_t Annotations; + uint8_t Type; + }; + }; + + uint32_t ChildCountFwdBckLo; //24 : 8 + + union { + uint32_t AnnotationStartFwdBckHi; + struct { + uint16_t AnnotationStart; + uint16_t FwdBckHi; + }; + }; + + void SetFwdBck(uint32_t v) { + FwdBckHi = v >> 8; + ChildCountFwdBckLo &= 0xFFFFFF; + ChildCountFwdBckLo |= v << 24; + } + +public: DxcHLSLNode() = default; - DxcHLSLNode(D3D12_HLSL_NODE_TYPE NodeType, uint32_t LocalId, - uint32_t AnnotationStart, uint32_t ChildCount, uint32_t ParentId, - uint16_t AnnotationCount) - : LocalIdParentLo(LocalId | (ParentId << 24)), - ChildCountPad(ChildCount), - AnnotationStartPad(AnnotationStart), - ParentHiAnnotationsType( - (uint32_t(NodeType) << 26) | - (uint32_t(AnnotationCount) << 16) | - (ParentId >> 8)) { + DxcHLSLNode(D3D12_HLSL_NODE_TYPE NodeType, bool IsFwdDeclare, + uint32_t LocalId, uint16_t AnnotationStart, uint32_t ChildCount, + uint32_t ParentId, uint8_t AnnotationCount) + : LocalIdParentLo(LocalId | (ParentId << 24)), ParentHi(ParentId >> 8), + Annotations(AnnotationCount), Type(NodeType), + ChildCountFwdBckLo(ChildCount | (0xFFu << 24)), FwdBckHi(0xFFFF), + AnnotationStart(AnnotationStart) { assert(NodeType >= D3D12_HLSL_NODE_TYPE_START && NodeType <= D3D12_HLSL_NODE_TYPE_END && "Invalid enum value"); @@ -52,41 +73,90 @@ struct DxcHLSLNode { assert(LocalId < ((1 << 24) - 1) && "LocalId out of bounds"); assert(ParentId < ((1 << 24) - 1) && "ParentId out of bounds"); assert(ChildCount < ((1 << 24) - 1) && "ChildCount out of bounds"); - assert(AnnotationCount < (1 << 10) && "AnnotationCount out of bounds"); - assert(AnnotationStart < ((1 << 20) - 1) && - "AnnotationStart out of bounds"); + if (IsFwdDeclare) { + + assert(!AnnotationCount && + "Fwd declares aren't allowed to have annotations"); + + assert(!ChildCount && + "Fwd declares aren't allowed to have children"); + + Type |= 0x80; + } + } + + bool IsFwdDeclare() const { return Type >> 7; } + + // FwdBck is the only one that is allowed to break the DAG. + // Example: + // Node 0 (struct T;) <- IsFwdDeclare() and points to definition + // Node 1 uses struct T; + // Node 2 (struct T { float T; };) <- no fwd declare and points to fwd + // declare. + // + // So the following are defined: + // IsFwdDeclare() && IsFwdDefined(): GetFwdBck() should point to a valid node + // that points back to the fwd declare. + // !IsFwdDeclare() && IsFwdDefined(): GetFwdBck() should point to a valid fwd + // declare that points back to it. + // Backwards declare should point to a NodeId < self and Forwards to > self. + // Forward declares aren't allowed to have any children. + // If there's a name, they should match. + // Must be same node type too. + // Only allowed on functions, struct/union and enums. + + uint32_t GetFwdBck() const { + return uint32_t(ChildCountFwdBckLo >> 24) | (uint32_t(FwdBckHi) << 8); + } + + bool IsFwdBckDefined() const { return GetFwdBck() != ((1 << 24) - 1); } + + void ResolveFwdDeclare(uint32_t SelfId, DxcHLSLNode &Definition, + uint32_t DefinitionId) { + + assert(SelfId < ((1 << 24) - 1) && "SelfId out of bounds"); + assert(DefinitionId < ((1 << 24) - 1) && "DefinitionId out of bounds"); + assert(DefinitionId != SelfId && "NodeId can't be definition id!"); + assert(IsFwdDeclare() && + "Can't run ResolveFwdDeclare on a node that's one"); + + assert(!Definition.IsFwdBckDefined() && !IsFwdBckDefined() && + "Fwd & backward declare must not be defined yet"); + + SetFwdBck(DefinitionId); + Definition.SetFwdBck(SelfId); } // For example if Enum, maps into Enums[LocalId] uint32_t GetLocalId() const { return LocalIdParentLo << 8 >> 8; } - uint32_t GetAnnotationStart() const { return AnnotationStartPad; } + uint32_t GetAnnotationStart() const { return AnnotationStart; } D3D12_HLSL_NODE_TYPE GetNodeType() const { - return D3D12_HLSL_NODE_TYPE(ParentHiAnnotationsType >> 26); + return D3D12_HLSL_NODE_TYPE(Type & 0x7F); } // Includes recursive children - uint32_t GetChildCount() const { return ChildCountPad; } + uint32_t GetChildCount() const { return ChildCountFwdBckLo << 8 >> 8; } - uint32_t GetAnnotationCount() const { - return uint32_t(ParentHiAnnotationsType << 6 >> (32 - 10)); - } + uint32_t GetAnnotationCount() const { return Annotations; } uint32_t GetParentId() const { - return uint32_t(LocalIdParentLo >> 24) | uint32_t(ParentHiAnnotationsType << 16 >> 8); + return uint32_t(LocalIdParentLo >> 24) | (uint32_t(ParentHi) << 8); } void IncreaseChildCount() { - assert(ChildCountPad < ((1 << 24) - 1) && "Child count out of bounds"); - ++ChildCountPad; + assert(GetChildCount() < ((1 << 24) - 1) && "Child count out of bounds"); + ++ChildCountFwdBckLo; } bool operator==(const DxcHLSLNode &other) const { return LocalIdParentLo == other.LocalIdParentLo && - ParentHiAnnotationsType == other.ParentHiAnnotationsType && - ChildCountPad == other.ChildCountPad; + ParentHiAnnotationsType32 == other.ParentHiAnnotationsType32 && + ChildCountFwdBckLo == other.ChildCountFwdBckLo && + AnnotationStartFwdBckHi == other.AnnotationStartFwdBckHi; } + }; struct DxcHLSLNodeSymbol { @@ -105,7 +175,7 @@ struct DxcHLSLNodeSymbol { struct { uint16_t SourceColumnStartLo; uint16_t SourceColumnEndLo; - uint32_t ColumnHiSourceLinePad; // 2 : 20 : 10 + uint32_t ColumnHiSourceLinePad; // 6 : 6 : 20 }; uint64_t SourceColumnStartEndLo; }; @@ -120,26 +190,26 @@ struct DxcHLSLNodeSymbol { SourceColumnStartLo(uint16_t(SourceColumnStart)), SourceColumnEndLo(uint16_t(SourceColumnEnd)), ColumnHiSourceLinePad((SourceColumnStart >> 16) | - (SourceColumnEnd >> 16 << 1) | - (SourceLineStart << 2)) { + (SourceColumnEnd >> 16 << 6) | + (SourceLineStart << 12)) { - assert(SourceColumnStart < (1 << 17) && "SourceColumnStart out of bounds"); - assert(SourceColumnEnd < (1 << 17) && "SourceColumnEnd out of bounds"); + assert(SourceColumnStart < (1 << 22) && "SourceColumnStart out of bounds"); + assert(SourceColumnEnd < (1 << 22) && "SourceColumnEnd out of bounds"); assert(SourceLineStart < ((1 << 20) - 1) && "SourceLineStart out of bounds"); } uint32_t GetSourceLineStart() const { - return uint32_t(ColumnHiSourceLinePad >> 2); + return uint32_t(ColumnHiSourceLinePad >> 12); } uint32_t GetSourceColumnStart() const { - return SourceColumnStartLo | ((ColumnHiSourceLinePad & 1) << 16); + return SourceColumnStartLo | ((ColumnHiSourceLinePad & 0x3F) << 16); } uint32_t GetSourceColumnEnd() const { - return SourceColumnEndLo | ((ColumnHiSourceLinePad & 2) << 15); + return SourceColumnEndLo | ((ColumnHiSourceLinePad & (0x3F << 6)) << 10); } bool operator==(const DxcHLSLNodeSymbol &other) const { @@ -453,21 +523,21 @@ struct DxcHLSLReflectionData { uint32_t AutoBindingSpace, D3D12_HLSL_REFLECTION_FEATURE Features, bool DefaultRowMaj); - bool IsSameNonDebug(const DxcHLSLReflectionData &other) const { - return StringsNonDebug == other.StringsNonDebug && Nodes == other.Nodes && - Registers == other.Registers && Functions == other.Functions && - Enums == other.Enums && EnumValues == other.EnumValues && - Annotations == other.Annotations && Arrays == other.Arrays && - ArraySizes == other.ArraySizes && - MemberTypeIds == other.MemberTypeIds && Types == other.Types && - Buffers == other.Buffers; - } - - bool operator==(const DxcHLSLReflectionData &other) const { - return IsSameNonDebug(other) && Strings == other.Strings && - Sources == other.Sources && NodeSymbols == other.NodeSymbols && - MemberNameIds == other.MemberNameIds && - TypeNameIds == other.TypeNameIds; + bool IsSameNonDebug(const DxcHLSLReflectionData &Other) const { + return StringsNonDebug == Other.StringsNonDebug && Nodes == Other.Nodes && + Registers == Other.Registers && Functions == Other.Functions && + Enums == Other.Enums && EnumValues == Other.EnumValues && + Annotations == Other.Annotations && Arrays == Other.Arrays && + ArraySizes == Other.ArraySizes && + MemberTypeIds == Other.MemberTypeIds && Types == Other.Types && + Buffers == Other.Buffers; + } + + bool operator==(const DxcHLSLReflectionData &Other) const { + return IsSameNonDebug(Other) && Strings == Other.Strings && + Sources == Other.Sources && NodeSymbols == Other.NodeSymbols && + MemberNameIds == Other.MemberNameIds && + TypeNameIds == Other.TypeNameIds; } }; diff --git a/include/dxc/config.h b/include/dxc/config.h new file mode 100644 index 0000000000..c7dce25e33 --- /dev/null +++ b/include/dxc/config.h @@ -0,0 +1,4 @@ +/* Disable overriding memory allocators. */ +/* #undef DXC_DISABLE_ALLOCATOR_OVERRIDES */ +/* Generate a trap if an hlsl::Exception is thrown during code generation */ +/* #undef DXC_CODEGEN_EXCEPTIONS_TRAP */ diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 70611a4c56..8651d7ac4a 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -71,7 +71,7 @@ struct IDxcRewriter2 : public IDxcRewriter { }; //Expose HLSL reflection before DXIL/SPIRV generation. -//(Ideally ran after the preprocessed HLSL is obtained). +//(Ran after the preprocessed HLSL is obtained). //This is useful to avoid custom parsers from reinventing the wheel. //You could use it to find all entrypoints even if [shader("")] isn't used, //Find struct/enum information, find out about optimized out registers, etc. @@ -90,31 +90,31 @@ enum D3D12_HLSL_REFLECTION_FEATURE { D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES = 1 << 3, // Variables, structs, functions defined in functions, scopes & structs - D3D12_HLSL_REFLECTION_FEATURE_SCOPES = 1 << 4, + //TODO: D3D12_HLSL_REFLECTION_FEATURE_SCOPES = 1 << 4, // Variables not included in $Global or cbuffers - D3D12_HLSL_REFLECTION_FEATURE_VARIABLES = 1 << 5, + //TODO: D3D12_HLSL_REFLECTION_FEATURE_VARIABLES = 1 << 5, // Symbol info (stripping this will remove names and file location info) - D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO = 1 << 6, + D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO = 1 << 16, D3D12_HLSL_REFLECTION_FEATURE_ALL = D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - 1 }; inline D3D12_HLSL_REFLECTION_FEATURE &operator|=(D3D12_HLSL_REFLECTION_FEATURE &a, D3D12_HLSL_REFLECTION_FEATURE b) { - return a = (D3D12_HLSL_REFLECTION_FEATURE)((uint32_t)a | (uint32_t)b); + return a = (D3D12_HLSL_REFLECTION_FEATURE)(uint32_t(a) | uint32_t(b)); } inline D3D12_HLSL_REFLECTION_FEATURE & operator&=(D3D12_HLSL_REFLECTION_FEATURE &a, D3D12_HLSL_REFLECTION_FEATURE b) { - return a = (D3D12_HLSL_REFLECTION_FEATURE)((uint32_t)a & (uint32_t)b); + return a = (D3D12_HLSL_REFLECTION_FEATURE)(uint32_t(a) & uint32_t(b)); } inline D3D12_HLSL_REFLECTION_FEATURE operator~(D3D12_HLSL_REFLECTION_FEATURE a) { - return (D3D12_HLSL_REFLECTION_FEATURE) ~(uint32_t)a; + return (D3D12_HLSL_REFLECTION_FEATURE) ~uint32_t(a); } struct D3D12_HLSL_REFLECTION_DESC { @@ -123,8 +123,10 @@ struct D3D12_HLSL_REFLECTION_DESC { UINT ResourceCount; UINT FunctionCount; UINT EnumCount; - UINT StructCount; UINT NodeCount; + UINT TypeCount; + UINT StructCount; + UINT UnionCount; }; struct D3D12_HLSL_FUNCTION_DESC { @@ -171,13 +173,17 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_ENUM, D3D12_HLSL_NODE_TYPE_ENUM_VALUE, D3D12_HLSL_NODE_TYPE_NAMESPACE, - D3D12_HLSL_NODE_TYPE_VARIABLE, // LocalId points to the type for a variable - //D3D12_HLSL_NODE_TYPE_TYPEDEF, - //D3D12_HLSL_NODE_TYPE_USING, - // TODO: Parameter, + D3D12_HLSL_NODE_TYPE_VARIABLE, // localId points to the type + D3D12_HLSL_NODE_TYPE_TYPEDEF, // ^ + D3D12_HLSL_NODE_TYPE_STRUCT, // has Variables as member like buffers do, localId is unused + D3D12_HLSL_NODE_TYPE_UNION, // ^ + // TODO: D3D12_HLSL_NODE_TYPE_USING, + // TODO: D3D12_HLSL_NODE_TYPE_PARAMETER, + + D3D12_HLSL_NODE_TYPE_RESERVED = 1 << 7, //Highest bit; reserved as an indicator for fwd declarations D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_VARIABLE + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_UNION }; struct D3D12_HLSL_NODE { @@ -187,6 +193,8 @@ struct D3D12_HLSL_NODE { UINT ChildCount; UINT Parent; UINT AnnotationCount; + UINT FwdBckDeclareNode; //If UINT_MAX has no forward / backward declare + BOOL IsFwdDeclare; }; struct D3D12_HLSL_NODE_SYMBOL { @@ -201,7 +209,6 @@ typedef interface ID3D12ShaderReflectionConstantBuffer ID3D12ShaderReflectionConstantBuffer; typedef struct _D3D12_SHADER_INPUT_BIND_DESC D3D12_SHADER_INPUT_BIND_DESC; -typedef interface ID3D12ShaderReflectionVariable ID3D12ShaderReflectionVariable; typedef interface ID3D12FunctionParameterReflection ID3D12FunctionParameterReflection; typedef interface ID3D12ShaderReflectionType ID3D12ShaderReflectionType; typedef interface IDxcHLSLReflection IDxcHLSLReflection; @@ -235,12 +242,21 @@ DECLARE_INTERFACE(IDxcHLSLReflection) { (THIS_ _In_ UINT FunctionIndex, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) PURE; + /*TODO: // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) - (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE; + (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE;*/ STDMETHOD(GetStructTypeByIndex) - (THIS_ _In_ UINT StructIndex, _Outptr_ ID3D12ShaderReflectionType **ppType) + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) + PURE; + + STDMETHOD(GetUnionTypeByIndex) + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) + PURE; + + STDMETHOD(GetTypeByIndex) + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; STDMETHOD(GetEnumDesc) @@ -296,13 +312,19 @@ DECLARE_INTERFACE(IDxcHLSLReflection) { (THIS_ _In_ LPCSTR Name) PURE; STDMETHOD(GetFunctionDescByName) - (THIS_ _In_ LPCSTR Name, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC * pDesc) PURE; + (THIS_ _In_ LPCSTR Name, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) PURE; STDMETHOD(GetResourceBindingDescByName) (THIS_ _In_ LPCSTR Name, _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE; STDMETHOD(GetStructTypeByName) (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + + STDMETHOD(GetUnionTypeByName) + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + + STDMETHOD(GetTypeByName) + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; }; #undef INTERFACE diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 16fc089895..764010fadf 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -37,79 +37,126 @@ static uint32_t RegisterString(DxcHLSLReflectionData &Refl, if (isNonDebug) { - assert(Refl.StringsNonDebug.size() < (uint32_t)-1 && "Strings overflow"); + assert(Refl.StringsNonDebug.size() < uint32_t(-1) && "Strings overflow"); auto it = Refl.StringsToIdNonDebug.find(Name); if (it != Refl.StringsToIdNonDebug.end()) return it->second; - uint32_t stringId = (uint32_t)Refl.StringsNonDebug.size(); + uint32_t stringId = uint32_t(Refl.StringsNonDebug.size()); Refl.StringsNonDebug.push_back(Name); Refl.StringsToIdNonDebug[Name] = stringId; return stringId; } - assert(Refl.Strings.size() < (uint32_t)-1 && "Strings overflow"); + assert(Refl.Strings.size() < uint32_t(-1) && "Strings overflow"); auto it = Refl.StringsToId.find(Name); if (it != Refl.StringsToId.end()) return it->second; - uint32_t stringId = (uint32_t) Refl.Strings.size(); + uint32_t stringId = uint32_t(Refl.Strings.size()); Refl.Strings.push_back(Name); Refl.StringsToId[Name] = stringId; return stringId; } -static uint32_t PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, - const LangOptions &LangOpts, - const std::string &UnqualifiedName, Decl *Decl, - D3D12_HLSL_NODE_TYPE Type, uint32_t ParentNodeId, - uint32_t LocalId, const SourceRange *Range = nullptr) { - - assert(Refl.Nodes.size() < (uint32_t)(1 << 24) && "Nodes overflow"); - assert(LocalId < (uint32_t)(1 << 24) && "LocalId overflow"); +static uint32_t +PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, + const LangOptions &LangOpts, const std::string &UnqualifiedName, + Decl *DeclSelf, D3D12_HLSL_NODE_TYPE Type, uint32_t ParentNodeId, + uint32_t LocalId, const SourceRange *Range = nullptr, + std::unordered_map *FwdDecls = nullptr) { + + assert(Refl.Nodes.size() < (1 << 24) && "Nodes overflow"); + assert(LocalId < (1 << 24) && "LocalId overflow"); uint32_t nodeId = Refl.Nodes.size(); - uint32_t annotationStart = (uint32_t) Refl.Annotations.size(); - uint16_t annotationCount = 0; + uint16_t annotationStart = uint16_t(Refl.Annotations.size()); + uint8_t annotationCount = 0; - if (Decl) { - for (const Attr *attr : Decl->attrs()) { + if (DeclSelf) { + for (const Attr *attr : DeclSelf->attrs()) { if (const AnnotateAttr *annotate = dyn_cast(attr)) { - assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); + assert(Refl.Annotations.size() < (1 << 16) && "Out of annotations"); Refl.Annotations.push_back(DxcHLSLAnnotation( RegisterString(Refl, annotate->getAnnotation().str(), true), false)); - assert(annotationCount != uint16_t(-1) && + assert(annotationCount != uint8_t(-1) && "Annotation count out of bounds"); ++annotationCount; } else if (const HLSLShaderAttr *shaderAttr = dyn_cast(attr)) { - assert(Refl.Annotations.size() < (1 << 20) && "Out of annotations"); + assert(Refl.Annotations.size() < (1 << 16) && "Out of annotations"); Refl.Annotations.push_back(DxcHLSLAnnotation( RegisterString( Refl, "shader(\"" + shaderAttr->getStage().str() + "\")", true), true)); - assert(annotationCount != uint16_t(-1) && + assert(annotationCount != uint8_t(-1) && "Annotation count out of bounds"); ++annotationCount; } } } + bool isFwdDeclare = false; + bool canHaveFwdDeclare = false; + Decl *fwdDeclare = nullptr; + + if (DeclSelf) { + + if (FunctionDecl *func = dyn_cast(DeclSelf)) { + isFwdDeclare = !func->doesThisDeclarationHaveABody(); + fwdDeclare = func->getCanonicalDecl(); + canHaveFwdDeclare = true; + } + + else if (EnumDecl *enm = dyn_cast(DeclSelf)) { + isFwdDeclare = !enm->isCompleteDefinition(); + fwdDeclare = enm->getCanonicalDecl(); + canHaveFwdDeclare = true; + } + + else if (RecordDecl *rec = dyn_cast(DeclSelf)) { + + isFwdDeclare = !rec->isCompleteDefinition(); + fwdDeclare = rec->getCanonicalDecl(); + canHaveFwdDeclare = true; + + if (isFwdDeclare && rec->isImplicit()) //Inner ghost node + return uint32_t(-1); + } + } + + uint32_t currId = uint32_t(Refl.Nodes.size()); + + if (canHaveFwdDeclare) { + + assert(FwdDecls && "Fwd decl requires FwdDecls map to be present"); + + // Multiple fwd declare, ignore + if (isFwdDeclare && FwdDecls->find(fwdDeclare) != FwdDecls->end()) + return uint32_t(-1); + + if (isFwdDeclare) + (*FwdDecls)[fwdDeclare] = currId; + } + + Refl.Nodes.push_back(DxcHLSLNode{Type, isFwdDeclare, LocalId, annotationStart, + 0, ParentNodeId, annotationCount}); + if (Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { uint16_t sourceLineCount = 0; @@ -117,10 +164,10 @@ static uint32_t PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager uint32_t sourceColumnStart = 0; uint32_t sourceColumnEnd = 0; - uint16_t sourceId = (uint16_t)-1; + uint16_t sourceId = uint16_t(-1); - SourceRange range = - Decl ? Decl->getSourceRange() : (Range ? *Range : SourceRange()); + SourceRange range = DeclSelf ? DeclSelf->getSourceRange() + : (Range ? *Range : SourceRange()); SourceLocation start = range.getBegin(); SourceLocation end = range.getEnd(); @@ -163,14 +210,14 @@ static uint32_t PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager assert((endLine - startLine) < 65535 && "Source line count is limited to 16-bit"); assert(startLine < 1048576 && "Source line start is limited to 20-bit"); - assert(startCol < 131072 && "Column start is limited to 17-bit"); - assert(endCol < 131072 && "Column end is limited to 17-bit"); + assert(startCol < (1 << 22) && "Column start is limited to 22-bit"); + assert(endCol < (1 << 22) && "Column end is limited to 22-bit"); sourceLineCount = uint16_t(endLine - startLine + 1); sourceLineStart = startLine; sourceColumnStart = startCol; sourceColumnEnd = endCol; - sourceId = (uint16_t)i; + sourceId = uint16_t(i); } } @@ -181,8 +228,13 @@ static uint32_t PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager sourceColumnStart, sourceColumnEnd)); } - Refl.Nodes.push_back(DxcHLSLNode{Type, LocalId, annotationStart, 0, - ParentNodeId, annotationCount}); + // Link + + if (DeclSelf && fwdDeclare != DeclSelf && fwdDeclare && !isFwdDeclare) { + assert(FwdDecls && "Referencing fwd decl requires FwdDecls map to be present"); + uint32_t fwd = (*FwdDecls)[fwdDeclare]; + Refl.Nodes[fwd].ResolveFwdDeclare(fwd, Refl.Nodes[currId], currId); + } uint32_t parentParent = ParentNodeId; @@ -330,7 +382,7 @@ static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, else if (TypeName == "Texture2DMS") type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2DMS; - assert((shouldBeTexture2DMS == + assert((shouldBeTexture2DMS == (type.TextureDimension == D3D_SRV_DIMENSION_TEXTURE2DMS)) && "Texture2DMS used with Texture2D syntax or reverse"); @@ -352,10 +404,8 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, std::string typeName = recordDecl->getNameAsString(); - if (typeName.size() >= 17 && - typeName.substr(0, 17) == "RasterizerOrdered") { + if (typeName.size() >= 17 && typeName.substr(0, 17) == "RasterizerOrdered") typeName = typeName.substr(17); - } if (typeName == "SamplerState" || typeName == "SamplerComparisonState") { return {D3D_SIT_SAMPLER, typeName == "SamplerComparisonState" @@ -415,13 +465,13 @@ static uint32_t PushArray(DxcHLSLReflectionData &Refl, uint32_t ArraySizeFlat, const std::vector &ArraySize) { if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) - return (uint32_t)-1; + return uint32_t(-1); - assert(Refl.Arrays.size() < (uint32_t)((1u << 31) - 1) && "Arrays would overflow"); - uint32_t arrayId = (uint32_t)Refl.Arrays.size(); + assert(Refl.Arrays.size() < uint32_t((1u << 31) - 1) && "Arrays would overflow"); + uint32_t arrayId = uint32_t(Refl.Arrays.size()); - uint32_t arrayCountStart = (uint32_t)Refl.ArraySizes.size(); - uint32_t numArrayElements = std::min((size_t)8, ArraySize.size()); + uint32_t arrayCountStart = uint32_t(Refl.ArraySizes.size()); + uint32_t numArrayElements = std::min(size_t(8), ArraySize.size()); assert(Refl.ArraySizes.size() + numArrayElements < ((1 << 28) - 1) && "Array elements would overflow"); @@ -474,13 +524,11 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, policy.AnonymousTagLocations = false; policy.SuppressTagKeyword = true; + std::string name = forName.getUnqualifiedType().getAsString(policy); + bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; uint32_t nameId = - hasSymbols - ? RegisterString( - Refl, forName.getLocalUnqualifiedType().getAsString(policy), - false) - : uint32_t(-1); + hasSymbols ? RegisterString(Refl, name, false) : uint32_t(-1); uint32_t arrayId = PushArray(Refl, arraySize, arrayElem); uint32_t elementsOrArrayId = 0; @@ -610,7 +658,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, if (!standardType && recordDecl->isCompleteDefinition()) { - //Base types + // Base types if (CXXRecordDecl *cxxRecordDecl = dyn_cast(recordDecl)) if (cxxRecordDecl->getNumBases()) { @@ -631,12 +679,10 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, } } - //Inner types + // Inner types for (Decl *decl : recordDecl->decls()) { - // TODO: We could query other types VarDecl - FieldDecl *fieldDecl = dyn_cast(decl); if (!fieldDecl) @@ -752,15 +798,15 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, //Insert - assert(Refl.Types.size() < (uint32_t)-1 && "Type id out of bounds"); + assert(Refl.Types.size() < uint32_t(-1) && "Type id out of bounds"); DxcHLSLType hlslType(baseType, elementsOrArrayId, cls, type, rows, columns, membersCount, membersOffset); - uint32_t i = 0, j = (uint32_t)Refl.Types.size(); + uint32_t i = 0, j = uint32_t(Refl.Types.size()); for (; i < j; ++i) - if (Refl.Types[i] == hlslType) + if (Refl.Types[i] == hlslType && (!hasSymbols || Refl.TypeNameIds[i] == nameId)) break; if (i == j) { @@ -809,7 +855,7 @@ static void FillReflectionRegisterAt( uint32_t nodeId = PushNextNodeId( Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, - (uint32_t)Refl.Registers.size()); + uint32_t(Refl.Registers.size())); uint32_t arrayId = PushArray(Refl, ArraySizeFlat, ArraySize); @@ -817,14 +863,14 @@ static void FillReflectionRegisterAt( D3D_CBUFFER_TYPE bufferType = GetBufferType(inputType.RegisterType); if(bufferType != D3D_CT_INTERFACE_POINTERS) { - bufferId = (uint32_t) Refl.Buffers.size(); + bufferId = uint32_t(Refl.Buffers.size()); Refl.Buffers.push_back({bufferType, nodeId}); } DxcHLSLRegister regD3D12 = { inputType.RegisterType, ArraySizeFlat, - (uint32_t)inputType.RegisterFlags, + uint32_t(inputType.RegisterFlags), inputType.TextureValue, inputType.TextureDimension, nodeId, @@ -930,8 +976,8 @@ uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, uint32_t NodeId, D3D_CBUFFER_TYPE Type, bool DefaultRowMaj) { - assert(Refl.Buffers.size() < (uint32_t)-1 && "Buffer id out of bounds"); - uint32_t bufferId = (uint32_t)Refl.Buffers.size(); + assert(Refl.Buffers.size() < uint32_t(-1) && "Buffer id out of bounds"); + uint32_t bufferId = uint32_t(Refl.Buffers.size()); RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), DefaultRowMaj, NodeId); @@ -940,7 +986,7 @@ uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, return bufferId; } -/* +/* TODO: static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, DxcHLSLReflectionData &Refl, const SourceManager &SM, uint32_t ParentNodeId) { @@ -989,14 +1035,13 @@ static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, //It's a struct, add parameters recursively }*/ -static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, - DiagnosticsEngine &Diags, - const SourceManager &SM, - DxcHLSLReflectionData &Refl, - uint32_t AutoBindingSpace, - uint32_t Depth, - D3D12_HLSL_REFLECTION_FEATURE Features, - uint32_t ParentNodeId, bool DefaultRowMaj) { +static void +RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, + DiagnosticsEngine &Diags, const SourceManager &SM, + DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, + uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, + uint32_t ParentNodeId, bool DefaultRowMaj, + std::unordered_map &FwdDecls) { PrintfStream pfStream; @@ -1012,12 +1057,12 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, // Traverse AST to grab reflection data - //TODO: Niels, scopes (if/switch/for/empty scope) + //TODO: scopes (if/switch/for/empty scope) for (Decl *it : Ctx.decls()) { SourceLocation Loc = it->getLocation(); - if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) + if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) //TODO: We might want to include these for a more complete picture. continue; if (HLSLBufferDecl *CBuffer = dyn_cast(it)) { @@ -1025,7 +1070,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) continue; - // TODO: Add for reflection even though it might not be important + // TODO: Add Depth > 0 for reflection if D3D12_HLSL_REFLECTION_FEATURE_SCOPES if (Depth != 0) continue; @@ -1033,7 +1078,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), CBuffer->getName(), CBuffer, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, - (uint32_t)Refl.Registers.size()); + uint32_t(Refl.Registers.size())); uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, SM, CBuffer, nodeId, D3D_CT_CBUFFER, DefaultRowMaj); @@ -1041,11 +1086,11 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DxcHLSLRegister regD3D12 = { D3D_SIT_CBUFFER, 1, - (uint32_t)D3D_SIF_USERPACKED, - (D3D_RESOURCE_RETURN_TYPE)0, + uint32_t(D3D_SIF_USERPACKED), + D3D_RESOURCE_RETURN_TYPE(0), D3D_SRV_DIMENSION_UNKNOWN, - 0, nodeId, + uint32_t(-1), bufferId}; Refl.Registers.push_back(regD3D12); @@ -1061,13 +1106,17 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), Func->getName(), Func, D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, - (uint32_t)Refl.Functions.size()); + uint32_t(Refl.Functions.size()), nullptr, &FwdDecls); + + if (nodeId == uint32_t(-1)) //Duplicate fwd definition + continue; bool hasDefinition = Func->hasBody(Definition); DxcHLSLFunction func = {nodeId, Func->getNumParams(), !Func->getReturnType().getTypePtr()->isVoidType(), hasDefinition}; + // TODO: /* for (uint32_t i = 0; i < func.NumParameters; ++i) AddFunctionParameters(ASTCtx, Func->getParamDecl(i)->getType(), @@ -1079,11 +1128,12 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, Refl.Functions.push_back(std::move(func)); - if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { + //TODO: + /*if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, nodeId, DefaultRowMaj); - } + }*/ } else if (TypedefDecl *Typedef = dyn_cast(it)) { @@ -1091,7 +1141,12 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) continue; - // Typedef->print(pfStream, printingPolicy); + uint32_t typeId = GenerateTypeInfo( + ASTCtx, Refl, Typedef->getUnderlyingType(), DefaultRowMaj); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), Typedef->getName(), + Typedef, D3D12_HLSL_NODE_TYPE_TYPEDEF, ParentNodeId, + typeId); } else if (TypeAliasDecl *TypeAlias = dyn_cast(it)) { @@ -1099,7 +1154,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) continue; - // TypeAlias->print(pfStream, printingPolicy); + // TODO: TypeAlias->print(pfStream, printingPolicy); } else if (EnumDecl *Enum = dyn_cast(it)) { @@ -1109,14 +1164,18 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, uint32_t nodeId = PushNextNodeId( Refl, SM, ASTCtx.getLangOpts(), Enum->getName(), Enum, - D3D12_HLSL_NODE_TYPE_ENUM, ParentNodeId, (uint32_t)Refl.Enums.size()); + D3D12_HLSL_NODE_TYPE_ENUM, ParentNodeId, + uint32_t(Refl.Enums.size()), nullptr, &FwdDecls); + + if (nodeId == uint32_t(-1)) // Duplicate fwd definition + continue; for (EnumConstantDecl *EnumValue : Enum->enumerators()) { uint32_t childNodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), EnumValue->getName(), EnumValue, D3D12_HLSL_NODE_TYPE_ENUM_VALUE, nodeId, - (uint32_t)Refl.EnumValues.size()); + uint32_t(Refl.EnumValues.size())); Refl.EnumValues.push_back( {EnumValue->getInitVal().getSExtValue(), childNodeId}); @@ -1155,12 +1214,22 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, Refl.Enums.push_back({nodeId, type}); } + else if (FieldDecl *fieldDecl = dyn_cast(it)) { + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, fieldDecl->getType(), DefaultRowMaj); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), fieldDecl->getName(), + fieldDecl, D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, + typeId); + } + else if (ValueDecl *ValDecl = dyn_cast(it)) { if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) continue; - //TODO: Handle values + //TODO: Handle values if D3D12_HLSL_REFLECTION_FEATURE_VARIABLES //ValDecl->print(pfStream); @@ -1179,7 +1248,8 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!IsHLSLResourceType(type)) continue; - // TODO: Add for reflection even though it might not be important + // TODO: Add Depth > 0 for reflection if + // D3D12_HLSL_REFLECTION_FEATURE_SCOPES if (Depth != 0) continue; @@ -1194,9 +1264,37 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) continue; - //RecDecl->print(pfStream, printingPolicy); - /*RecursiveReflectHLSL(*RecDecl, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, InclusionFlags, nodeId);*/ + bool isCompleteDefinition = RecDecl->isCompleteDefinition(); + + bool pushObj = false; + bool isStruct = RecDecl->getTagKind() == TTK_Struct; + + switch (RecDecl->getTagKind()) { + + case TTK_Struct: + case TTK_Union: + pushObj = true; + break; + + // TODO: case TTK_Interface: Is this HLSL's interface or something else? + // break; + } + + if (pushObj) { + + uint32_t self = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), RecDecl->getName(), RecDecl, + isStruct ? D3D12_HLSL_NODE_TYPE_STRUCT : D3D12_HLSL_NODE_TYPE_UNION, + ParentNodeId, 0, nullptr, &FwdDecls); + + if (self == uint32_t(-1)) // Duplicate fwd definition + continue; + + if (isCompleteDefinition) + RecursiveReflectHLSL(*RecDecl, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, self, + DefaultRowMaj, FwdDecls); + } } else if (NamespaceDecl *Namespace = dyn_cast(it)) { @@ -1210,7 +1308,7 @@ static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, RecursiveReflectHLSL(*Namespace, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, nodeId, - DefaultRowMaj); + DefaultRowMaj, FwdDecls); } } } @@ -1234,10 +1332,11 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(clang::CompilerInstance &Compiler, } Nodes.push_back( - DxcHLSLNode{D3D12_HLSL_NODE_TYPE_NAMESPACE, 0, 0, 0, 0xFFFF, 0}); + DxcHLSLNode{D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, 0, 0, 0xFFFF, 0}); + std::unordered_map fwdDecls; RecursiveReflectHLSL(Ctx, Compiler.getASTContext(), Diags, SM, *this, - AutoBindingSpace, 0, Features, 0, DefaultRowMaj); + AutoBindingSpace, 0, Features, 0, DefaultRowMaj, fwdDecls); } //TODO: Debug print code @@ -1269,10 +1368,11 @@ static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { - static const char *arr[] = {"Register", "Function", "Enum", "EnumValue", - "Namespace", "Variable"}; + static const char *arr[] = {"Register", "Function", "Enum", + "EnumValue", "Namespace", "Variable", + "Typedef", "Struct", "Union"}; - return arr[(int)type]; + return arr[uint32_t(type)]; } static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, @@ -1402,7 +1502,7 @@ static std::string PrintTypeInfo(const DxcHLSLReflectionData &Refl, } static void RecursePrintType(const DxcHLSLReflectionData &Refl, uint32_t TypeId, - uint32_t Depth, const char *Prefix = "") { + uint32_t Depth, const char *Prefix) { const DxcHLSLType &type = Refl.Types[TypeId]; @@ -1441,10 +1541,11 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - printf("%s%s %s\n", std::string(Depth - 1, '\t').c_str(), + printf("%s%s %s%s\n", std::string(Depth - 1, '\t').c_str(), NodeTypeToString(node.GetNodeType()).c_str(), hasSymbols ? Refl.Strings[Refl.NodeSymbols[NodeId].NameId].c_str() - : "(unknown)"); + : "(unknown)", + node.IsFwdDeclare() ? " (fwd declare)" : ""); for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) { @@ -1474,6 +1575,13 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, break; } + case D3D12_HLSL_NODE_TYPE_UNION: + case D3D12_HLSL_NODE_TYPE_STRUCT: //Children are Variables + break; + + // TODO: case D3D12_HLSL_NODE_TYPE_USING: + + case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: typeToPrint = localId; break; @@ -1499,11 +1607,6 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, break; } - //TODO: - //case D3D12_HLSL_NODE_TYPE_TYPEDEF: - //case D3D12_HLSL_NODE_TYPE_USING: - // break; - case D3D12_HLSL_NODE_TYPE_NAMESPACE: default: break; @@ -1511,7 +1614,7 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, } if (typeToPrint != (uint32_t)-1) - RecursePrintType(Refl, typeToPrint, Depth); + RecursePrintType(Refl, typeToPrint, Depth, ""); for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1, j); @@ -1558,17 +1661,17 @@ const T &UnsafeCast(const std::vector &Bytes, uint64_t Offset) { } template -void SkipPadding(uint64_t& Offset) { +void SkipPadding(uint64_t &Offset) { Offset = (Offset + alignof(T) - 1) / alignof(T) * alignof(T); } template -void Skip(uint64_t& Offset, const std::vector& Vec) { +void Skip(uint64_t &Offset, const std::vector &Vec) { Offset += Vec.size() * sizeof(T); } template -void Advance(uint64_t& Offset, const std::vector& Vec) { +void Advance(uint64_t &Offset, const std::vector &Vec) { SkipPadding(Offset); Skip(Offset, Vec); } @@ -1861,7 +1964,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if(Sources[i] >= header.Strings) throw std::invalid_argument("Source path out of bounds"); - for(uint32_t i = 0; i < header.Nodes; ++i) { + for (uint32_t i = 0; i < header.Nodes; ++i) { const DxcHLSLNode &node = Nodes[i]; @@ -1871,39 +1974,51 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes throw std::invalid_argument("Node " + std::to_string(i) + " points to invalid name or file name"); - if( - node.GetAnnotationStart() + node.GetAnnotationCount() > header.Annotations || + if (node.GetAnnotationStart() + node.GetAnnotationCount() > + header.Annotations || node.GetNodeType() > D3D12_HLSL_NODE_TYPE_END || - (i && node.GetParentId() >= i) || - i + node.GetChildCount() > header.Nodes - ) + (i && node.GetParentId() >= i) || + i + node.GetChildCount() > header.Nodes) throw std::invalid_argument("Node " + std::to_string(i) + " is invalid"); uint32_t maxValue = 1; + bool allowFwdDeclare = false; - switch(node.GetNodeType()) { + switch (node.GetNodeType()) { case D3D12_HLSL_NODE_TYPE_REGISTER: - maxValue = header.Registers; - break; - case D3D12_HLSL_NODE_TYPE_FUNCTION: - maxValue = header.Functions; - break; - case D3D12_HLSL_NODE_TYPE_ENUM: - maxValue = header.Enums; - break; - case D3D12_HLSL_NODE_TYPE_ENUM_VALUE: - maxValue = header.EnumValues; - break; - //TODO: - //case D3D12_HLSL_NODE_TYPE_TYPEDEF: - //case D3D12_HLSL_NODE_TYPE_USING: - case D3D12_HLSL_NODE_TYPE_VARIABLE: - maxValue = header.Types; - break; + maxValue = header.Registers; + break; + case D3D12_HLSL_NODE_TYPE_FUNCTION: + maxValue = header.Functions; + allowFwdDeclare = true; + break; + case D3D12_HLSL_NODE_TYPE_ENUM: + maxValue = header.Enums; + allowFwdDeclare = true; + break; + case D3D12_HLSL_NODE_TYPE_ENUM_VALUE: + maxValue = header.EnumValues; + break; + + // TODO: case D3D12_HLSL_NODE_TYPE_USING: + case D3D12_HLSL_NODE_TYPE_TYPEDEF: + case D3D12_HLSL_NODE_TYPE_VARIABLE: + maxValue = header.Types; + break; + + case D3D12_HLSL_NODE_TYPE_STRUCT: + case D3D12_HLSL_NODE_TYPE_UNION: + allowFwdDeclare = true; + break; } - if(node.GetLocalId() >= maxValue) - throw std::invalid_argument("Node " + std::to_string(i) + " has invalid localId"); + if (node.IsFwdDeclare() && !allowFwdDeclare) + throw std::invalid_argument("Node " + std::to_string(i) + + " is fwd declare but that's not permitted"); + + if (node.GetLocalId() >= maxValue) + throw std::invalid_argument("Node " + std::to_string(i) + + " has invalid localId"); } for(uint32_t i = 0; i < header.Registers; ++i) { @@ -1966,6 +2081,10 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLNode &node = Nodes[enm.NodeId]; + if (!node.IsFwdDeclare() && !node.GetChildCount()) + throw std::invalid_argument("Enum " + std::to_string(i) + + " has no values!"); + for (uint32_t j = 0; j < node.GetChildCount(); ++j) { const DxcHLSLNode &child = Nodes[enm.NodeId + 1 + j]; @@ -2181,9 +2300,65 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes } } + //Validate fwd & backwards declares + + for (uint32_t i = 0; i < header.Nodes; ++i) { + + const DxcHLSLNode &node = Nodes[i]; + + if (node.IsFwdBckDefined()) { + + uint32_t fwdBack = node.GetFwdBck(); + + if (Nodes[fwdBack].GetNodeType() != node.GetNodeType()) + throw std::invalid_argument( + "Node " + std::to_string(i) + + " (fwd/bck declare) points to element that of incompatible type"); + + if (hasSymbolInfo && NodeSymbols[fwdBack].NameId != NodeSymbols[i].NameId) + throw std::invalid_argument( + "Node " + std::to_string(i) + + " (fwd/bck declare) have mismatching name"); + + if (node.IsFwdDeclare()) { + + if (fwdBack <= i || fwdBack >= header.Nodes) + throw std::invalid_argument( + "Node " + std::to_string(i) + + " (fwd declare) points to invalid element"); + + if (Nodes[fwdBack].IsFwdDeclare()) + throw std::invalid_argument( + "Node " + std::to_string(i) + + " (fwd declare) points to element that is also a fwd declare"); + + if (node.GetChildCount() || node.GetAnnotationCount()) + throw std::invalid_argument( + "Node " + std::to_string(i) + + " (fwd declare) points to element with invalid child count, " + "or annotationCount"); + } + + else { + + if (fwdBack >= i) + throw std::invalid_argument( + "Node " + std::to_string(i) + + " (bck declare) points to invalid element"); + + if (!Nodes[fwdBack].IsFwdDeclare()) + throw std::invalid_argument( + "Node " + std::to_string(i) + + " (bck declare) points to element that is not a fwd declare"); + } + } + } + + //Finalize + if (MakeNameLookupTable) GenerateNameLookupTable(); -}; +} void DxcHLSLReflectionData::Printf() const { RecursePrint(*this, 0, 0, 0); } diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index fd7ca26a95..339a8c3f50 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -57,42 +57,498 @@ struct ASTHelper { bool bHasErrors; }; +// We can't return nullptr instead, since that doesn't match old behavior... + +class CHLSLInvalidSRType final : public ID3D12ShaderReflectionType { + + STDMETHOD(GetDesc)(D3D12_SHADER_TYPE_DESC *pDesc) override { return E_FAIL; } + + STDMETHOD_(ID3D12ShaderReflectionType *, GetMemberTypeByIndex) + (UINT Index) override; + + STDMETHOD_(ID3D12ShaderReflectionType *, GetMemberTypeByName) + (LPCSTR Name) override; + + STDMETHOD_(LPCSTR, GetMemberTypeName)(UINT Index) override { + return "$Invalid"; + } + + STDMETHOD(IsEqual)(ID3D12ShaderReflectionType *pType) override { + return E_FAIL; + } + STDMETHOD_(ID3D12ShaderReflectionType *, GetSubType)() override; + STDMETHOD_(ID3D12ShaderReflectionType *, GetBaseClass)() override; + STDMETHOD_(UINT, GetNumInterfaces)() override { return 0; } + STDMETHOD_(ID3D12ShaderReflectionType *, GetInterfaceByIndex) + (UINT uIndex) override; + + STDMETHOD(IsOfType)(ID3D12ShaderReflectionType *pType) override { + return E_FAIL; + } + + STDMETHOD(ImplementsInterface)(ID3D12ShaderReflectionType *pBase) override { + return E_FAIL; + } +}; +static CHLSLInvalidSRType g_InvalidSRType; + +ID3D12ShaderReflectionType *CHLSLInvalidSRType::GetMemberTypeByIndex(UINT) { + return &g_InvalidSRType; +} +ID3D12ShaderReflectionType *CHLSLInvalidSRType::GetMemberTypeByName(LPCSTR) { + return &g_InvalidSRType; +} +ID3D12ShaderReflectionType *CHLSLInvalidSRType::GetSubType() { + return &g_InvalidSRType; +} +ID3D12ShaderReflectionType *CHLSLInvalidSRType::GetBaseClass() { + return &g_InvalidSRType; +} +ID3D12ShaderReflectionType *CHLSLInvalidSRType::GetInterfaceByIndex(UINT) { + return &g_InvalidSRType; +} + +class CHLSLInvalidSRVariable final : public ID3D12ShaderReflectionVariable { + + STDMETHOD(GetDesc)(D3D12_SHADER_VARIABLE_DESC *pDesc) override { + return E_FAIL; + } + + STDMETHOD_(ID3D12ShaderReflectionType *, GetType)() override { + return &g_InvalidSRType; + } + + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetBuffer)() override; + + STDMETHOD_(UINT, GetInterfaceSlot)(UINT uIndex) override { return UINT_MAX; } +}; +static CHLSLInvalidSRVariable g_InvalidSRVariable; + +class CHLSLInvalidSRConstantBuffer final + : public ID3D12ShaderReflectionConstantBuffer { + + STDMETHOD(GetDesc)(D3D12_SHADER_BUFFER_DESC *pDesc) override { + return E_FAIL; + } + + STDMETHOD_(ID3D12ShaderReflectionVariable *, GetVariableByIndex) + (UINT Index) override { + return &g_InvalidSRVariable; + } + + STDMETHOD_(ID3D12ShaderReflectionVariable *, GetVariableByName) + (LPCSTR Name) override { return &g_InvalidSRVariable; } +}; +static CHLSLInvalidSRConstantBuffer g_InvalidSRConstantBuffer; + +ID3D12ShaderReflectionConstantBuffer *CHLSLInvalidSRVariable::GetBuffer() { + return &g_InvalidSRConstantBuffer; +} + +class CHLSLReflectionConstantBuffer; + +class CHLSLReflectionType final : public ID3D12ShaderReflectionType { + friend class CHLSLReflectionConstantBuffer; + +protected: + + std::string m_Name; + std::vector m_MemberNames; + std::unordered_map m_NameToMemberId; + std::vector m_MemberTypes; + CHLSLReflectionType *m_pBaseClass; + + const DxcHLSLReflectionData *m_Data; + uint32_t m_TypeId; + uint32_t m_Elements; + +public: + + STDMETHOD(IsEqual)(ID3D12ShaderReflectionType *pType) override { + // TODO: implement this check, if users actually depend on it + return S_FALSE; + } + + STDMETHOD(IsOfType)(ID3D12ShaderReflectionType *pType) override { + // TODO: implement `class`-related features, if requested + return S_FALSE; + } + + HRESULT Initialize( + const DxcHLSLReflectionData &Data, uint32_t TypeId, + std::vector &Types /* Only access < TypeId*/) { + + m_TypeId = TypeId; + m_Elements = 0; + m_Data = &Data; + + const DxcHLSLType &type = Data.Types[TypeId]; + + if (type.IsArray()) { + + m_Elements = type.Is1DArray() ? type.Get1DElements() : 1; + + if (type.IsMultiDimensionalArray()) { + + const DxcHLSLArray &arr = + Data.Arrays[type.GetMultiDimensionalArrayId()]; + + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) + m_Elements *= Data.ArraySizes[arr.ArrayStart() + i]; + } + } + + bool hasNames = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (hasNames) + m_Name = Data.TypeNameIds[TypeId]; + + uint32_t memberCount = type.GetMemberCount(); + + m_MemberNames.resize(memberCount); + m_MemberTypes.resize(memberCount); + m_NameToMemberId.clear(); + + for (uint32_t i = 0; i < memberCount; ++i) { + + uint32_t memberId = type.GetMemberStart() + i; + + m_MemberTypes[i] = &Types[Data.MemberTypeIds[memberId]]; + + if (hasNames) { + + const std::string &name = Data.Strings[Data.MemberNameIds[memberId]]; + + m_MemberNames[i] = name; + m_NameToMemberId[name] = i; + } + } + + if (type.BaseClass != uint32_t(-1)) + m_pBaseClass = &Types[type.BaseClass]; + } + + STDMETHOD(GetDesc)(D3D12_SHADER_TYPE_DESC *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + const DxcHLSLType &type = m_Data->Types[m_TypeId]; + + *pDesc = D3D12_SHADER_TYPE_DESC { + + (D3D_SHADER_VARIABLE_CLASS) type.Class, + (D3D_SHADER_VARIABLE_TYPE) type.Type, + type.Rows, + type.Columns, + + m_Elements, + uint32_t(m_MemberTypes.size()), + 0, //TODO: Offset if we have one + m_Name.c_str() + }; + + return S_OK; + } + + STDMETHOD_(ID3D12ShaderReflectionType *, GetMemberTypeByIndex) + (UINT Index) override { + + if (Index >= m_MemberTypes.size()) + return &g_InvalidSRType; + + return m_MemberTypes[Index]; + } + + STDMETHOD_(ID3D12ShaderReflectionType *, GetMemberTypeByName) + (LPCSTR Name) override { + + if (!Name) + return &g_InvalidSRType; + + auto it = m_NameToMemberId.find(Name); + return it == m_NameToMemberId.end() + ? (ID3D12ShaderReflectionType *)&g_InvalidSRType + : m_MemberTypes[it->second]; + } + + STDMETHOD_(LPCSTR, GetMemberTypeName)(UINT Index) override { + + if (Index >= m_MemberTypes.size()) + return nullptr; + + return m_MemberNames[Index].c_str(); + } + + STDMETHOD_(ID3D12ShaderReflectionType *, GetSubType)() override { + return nullptr; + } + + STDMETHOD_(ID3D12ShaderReflectionType *, GetBaseClass)() override { + return m_pBaseClass; + } + + STDMETHOD_(UINT, GetNumInterfaces)() override { + // HLSL interfaces have been deprecated + return 0; + } + + STDMETHOD(ImplementsInterface)(ID3D12ShaderReflectionType *pBase) override { + // HLSL interfaces have been deprecated + return S_FALSE; + } + + STDMETHOD_(ID3D12ShaderReflectionType *, GetInterfaceByIndex) + (UINT uIndex) override { + // HLSL interfaces have been deprecated + return nullptr; + } +}; + +class CHLSLReflectionVariable final : public ID3D12ShaderReflectionVariable { +protected: + CHLSLReflectionType *m_pType; + CHLSLReflectionConstantBuffer *m_pBuffer; + std::string m_Name; + +public: + void Initialize(CHLSLReflectionConstantBuffer *pBuffer, + CHLSLReflectionType *pType, std::string &&Name) { + m_pBuffer = pBuffer; + m_pType = pType; + m_Name = Name; + } + + LPCSTR GetName() const { return m_Name.c_str(); } + + STDMETHOD(GetDesc)(D3D12_SHADER_VARIABLE_DESC *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + *pDesc = D3D12_SHADER_VARIABLE_DESC{ + GetName(), + 0, // TODO: offset and size next time + 0, D3D_SVF_USED, NULL, uint32_t(-1), 0, uint32_t(-1), 0}; + + return S_OK; + } + + STDMETHOD_(ID3D12ShaderReflectionType *, GetType) + () override { return m_pType; } + + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetBuffer)() override; + + STDMETHOD_(UINT, GetInterfaceSlot)(UINT uArrayIndex) override { + return UINT_MAX; + } +}; + +class CHLSLReflectionConstantBuffer final + : public ID3D12ShaderReflectionConstantBuffer { +protected: + const DxcHLSLReflectionData *m_Data; + uint32_t m_ChildCount; + uint32_t m_BufferId; + uint32_t m_NodeId; + std::vector m_Variables; + std::unordered_map m_VariablesByName; + + // For StructuredBuffer arrays, Name will have [0] appended for each dimension + // to match fxc behavior. + std::string m_ReflectionName; + +public: + CHLSLReflectionConstantBuffer() = default; + CHLSLReflectionConstantBuffer(CHLSLReflectionConstantBuffer &&other) { + m_BufferId = other.m_BufferId; + m_NodeId = other.m_NodeId; + m_Data = other.m_Data; + m_ChildCount = other.m_ChildCount; + std::swap(m_ReflectionName, other.m_ReflectionName); + std::swap(m_Variables, other.m_Variables); + std::swap(m_VariablesByName, other.m_VariablesByName); + } + + void Initialize(const DxcHLSLReflectionData &Data, uint32_t NodeId, + const std::unordered_map> + &ChildrenNonRecursive, + CHLSLReflectionConstantBuffer *ConstantBuffer, + std::vector &Types) { + + if (NodeId >= Data.Nodes.size()) + return; + + const DxcHLSLNode &node = Data.Nodes[NodeId]; + + if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER) + return; + + const std::vector &children = ChildrenNonRecursive.at(NodeId); + + const DxcHLSLRegister ® = Data.Registers[node.GetLocalId()]; + + if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { + + m_ReflectionName = Data.Strings[Data.NodeSymbols[NodeId].NameId]; + + bool isCBuffer = reg.Type == D3D_SIT_CBUFFER; + + if (m_ReflectionName.size() && !isCBuffer) { + + uint32_t arrayDims = reg.ArrayId != uint32_t(-1) + ? Data.Arrays[reg.ArrayId].ArrayElem() + : (reg.BindCount > 1 ? 1 : 0); + + for (unsigned i = 0; i < arrayDims; ++i) + m_ReflectionName += "[0]"; + } + } + + else + m_ReflectionName.clear(); + + m_Data = &Data; + m_NodeId = NodeId; + m_ChildCount = uint32_t(children.size()); + m_BufferId = reg.BufferId; + + m_VariablesByName.clear(); + m_Variables.resize(children.size()); + + for (uint32_t i = 0, j = 0; i < m_ChildCount; ++i) { + + uint32_t childId = children[i]; + + std::string name; + + if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + name = Data.Strings[Data.NodeSymbols[childId].NameId]; + + uint32_t typeId = Data.Nodes[childId].GetLocalId(); + + m_Variables[i].Initialize(ConstantBuffer, &Types[typeId], + std::move(name)); + + if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + m_VariablesByName[m_Variables[i].GetName()] = i; + } + } + + LPCSTR GetName() const { return m_ReflectionName.c_str(); } + + STDMETHOD(GetDesc)(D3D12_SHADER_BUFFER_DESC *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + *pDesc = D3D12_SHADER_BUFFER_DESC{ + GetName(), m_Data->Buffers[m_BufferId].Type, m_ChildCount, + 0 // TODO: Size when we have it + }; + + return S_OK; + } + + STDMETHOD_(ID3D12ShaderReflectionVariable *, GetVariableByIndex) + (UINT Index) override { + + if (Index >= m_Variables.size()) + return &g_InvalidSRVariable; + + return &m_Variables[Index]; + } + + STDMETHOD_(ID3D12ShaderReflectionVariable *, GetVariableByName) + (LPCSTR Name) override { + + if (NULL == Name) + return &g_InvalidSRVariable; + + auto it = m_VariablesByName.find(Name); + + if (it == m_VariablesByName.end()) + return &g_InvalidSRVariable; + + return &m_Variables[it->second]; + } +}; + +ID3D12ShaderReflectionConstantBuffer *CHLSLReflectionVariable::GetBuffer() { + return m_pBuffer; +} + struct DxcHLSLReflection : public IDxcHLSLReflection { - DxcHLSLReflectionData data{}; - std::vector childCountsNonRecursive; - std::unordered_map> childrenNonRecursive; + DxcHLSLReflectionData Data{}; + + std::vector ChildCountsNonRecursive; + std::unordered_map> ChildrenNonRecursive; + + std::vector ConstantBuffers; + std::unordered_map NameToConstantBuffers; + + std::vector Types; + + std::vector StructIds; + std::vector UnionIds; + std::unordered_map NameToStructId; + std::unordered_map NameToUnionId; DxcHLSLReflection() = default; void Finalize() { - data.GenerateNameLookupTable(); + Data.GenerateNameLookupTable(); - childCountsNonRecursive.resize(data.Nodes.size()); - childrenNonRecursive.clear(); + ChildCountsNonRecursive.resize(Data.Nodes.size()); + ChildrenNonRecursive.clear(); - for (uint32_t i = 0; i < (uint32_t)data.Nodes.size(); ++i) { + for (uint32_t i = 0; i < uint32_t(Data.Nodes.size()); ++i) { - const DxcHLSLNode &node = data.Nodes[i]; + const DxcHLSLNode &node = Data.Nodes[i]; uint32_t childCount = 0; for (uint32_t j = 0; j < node.GetChildCount(); ++j, ++childCount) { - childrenNonRecursive[i].push_back(i + 1 + j); - j += data.Nodes[i + 1 + j].GetChildCount(); + ChildrenNonRecursive[i].push_back(i + 1 + j); + j += Data.Nodes[i + 1 + j].GetChildCount(); } - childCountsNonRecursive[i] = childCount; + ChildCountsNonRecursive[i] = childCount; } + + NameToConstantBuffers.clear(); + ConstantBuffers.resize(Data.Buffers.size()); + Types.resize(Data.Types.size()); + + for (uint32_t i = 0; i < (uint32_t)Data.Types.size(); ++i) + Types[i].Initialize(Data, i, Types); + + for (uint32_t i = 0; i < (uint32_t)Data.Buffers.size(); ++i) { + + ConstantBuffers[i].Initialize(Data, Data.Buffers[i].NodeId, + ChildrenNonRecursive, &ConstantBuffers[i], + Types); + + if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + NameToConstantBuffers[ConstantBuffers[i].GetName()] = i; + } + + //TODO: Lookup table to struct id and union id } - DxcHLSLReflection(DxcHLSLReflectionData &&moved) : data(moved) { + DxcHLSLReflection(DxcHLSLReflectionData &&moved) : Data(moved) { Finalize(); } DxcHLSLReflection &operator=(DxcHLSLReflection &&moved) { - data = std::move(moved.data); - Finalize(); + Data = std::move(moved.Data); + ChildCountsNonRecursive = std::move(moved.ChildCountsNonRecursive); + ChildrenNonRecursive = std::move(moved.ChildrenNonRecursive); + ConstantBuffers = std::move(moved.ConstantBuffers); + NameToConstantBuffers = std::move(moved.NameToConstantBuffers); + Types = std::move(moved.Types); + StructIds = std::move(moved.StructIds); + UnionIds = std::move(moved.UnionIds); + NameToStructId = std::move(moved.NameToStructId); + NameToUnionId = std::move(moved.NameToUnionId); return *this; } @@ -102,13 +558,15 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pDesc)); - *pDesc = {data.Features, - 0, //TODO: data.ConstantBuffers, - uint32_t(data.Registers.size()), - uint32_t(data.Functions.size()), - uint32_t(data.Enums.size()), - 0, // TODO: Structs - uint32_t(data.Nodes.size())}; + *pDesc = {Data.Features, + uint32_t(Data.Buffers.size()), + uint32_t(Data.Registers.size()), + uint32_t(Data.Functions.size()), + uint32_t(Data.Enums.size()), + uint32_t(Data.Nodes.size()), + uint32_t(Data.Types.size()), + uint32_t(StructIds.size()), + uint32_t(UnionIds.size())}; return S_OK; } @@ -119,25 +577,25 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pDesc)); - if (ResourceIndex >= data.Registers.size()) + if (ResourceIndex >= Data.Registers.size()) return E_INVALIDARG; - const DxcHLSLRegister ® = data.Registers[ResourceIndex]; + const DxcHLSLRegister ® = Data.Registers[ResourceIndex]; LPCSTR name = - data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - ? data.Strings[data.NodeSymbols[reg.NodeId].NameId].c_str() + Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + ? Data.Strings[Data.NodeSymbols[reg.NodeId].NameId].c_str() : ""; *pDesc = D3D12_SHADER_INPUT_BIND_DESC{ name, - (D3D_SHADER_INPUT_TYPE)reg.Type, + D3D_SHADER_INPUT_TYPE(reg.Type), uint32_t(-1), //Invalid bindPoint, depending on backend we might want to change it reg.BindCount, reg.uFlags, - (D3D_RESOURCE_RETURN_TYPE) reg.ReturnType, - (D3D_SRV_DIMENSION) reg.Dimension, + D3D_RESOURCE_RETURN_TYPE(reg.ReturnType), + D3D_SRV_DIMENSION(reg.Dimension), uint32_t(-1), // Also no valid data depending on backend uint32_t(-1), //Invalid space (see bindPoint ^) reg.NodeId @@ -151,18 +609,18 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pDesc)); - if (EnumIndex >= data.Enums.size()) + if (EnumIndex >= Data.Enums.size()) return E_INVALIDARG; - const DxcHLSLEnumDesc &enm = data.Enums[EnumIndex]; + const DxcHLSLEnumDesc &enm = Data.Enums[EnumIndex]; LPCSTR name = - data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - ? data.Strings[data.NodeSymbols[enm.NodeId].NameId].c_str() + Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + ? Data.Strings[Data.NodeSymbols[enm.NodeId].NameId].c_str() : ""; *pDesc = D3D12_HLSL_ENUM_DESC{ - name, uint32_t(data.Nodes[enm.NodeId].GetChildCount()), enm.Type}; + name, uint32_t(Data.Nodes[enm.NodeId].GetChildCount()), enm.Type}; return S_OK; } @@ -173,24 +631,24 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pValueDesc)); - if (EnumIndex >= data.Enums.size()) + if (EnumIndex >= Data.Enums.size()) return E_INVALIDARG; - const DxcHLSLEnumDesc &enm = data.Enums[EnumIndex]; - const DxcHLSLNode &parent = data.Nodes[enm.NodeId]; + const DxcHLSLEnumDesc &enm = Data.Enums[EnumIndex]; + const DxcHLSLNode &parent = Data.Nodes[enm.NodeId]; if (ValueIndex >= parent.GetChildCount()) return E_INVALIDARG; LPCSTR name = - data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - ? data.Strings[data.NodeSymbols[enm.NodeId].NameId].c_str() + Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + ? Data.Strings[Data.NodeSymbols[enm.NodeId].NameId].c_str() : ""; - const DxcHLSLNode &node = data.Nodes[enm.NodeId + 1 + ValueIndex]; + const DxcHLSLNode &node = Data.Nodes[enm.NodeId + 1 + ValueIndex]; *pValueDesc = - D3D12_HLSL_ENUM_VALUE{name, data.EnumValues[node.GetLocalId()].Value}; + D3D12_HLSL_ENUM_VALUE{name, Data.EnumValues[node.GetLocalId()].Value}; return S_OK; } @@ -201,19 +659,19 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pAnnotation)); - if (NodeId >= data.Nodes.size()) + if (NodeId >= Data.Nodes.size()) return E_INVALIDARG; - const DxcHLSLNode &node = data.Nodes[NodeId]; + const DxcHLSLNode &node = Data.Nodes[NodeId]; if (Index >= node.GetAnnotationCount()) return E_INVALIDARG; const DxcHLSLAnnotation &annotation = - data.Annotations[node.GetAnnotationStart() + Index]; + Data.Annotations[node.GetAnnotationStart() + Index]; *pAnnotation = D3D12_HLSL_ANNOTATION{ - data.StringsNonDebug[annotation.GetStringNonDebug()].c_str(), + Data.StringsNonDebug[annotation.GetStringNonDebug()].c_str(), annotation.GetIsBuiltin()}; return S_OK; @@ -225,14 +683,14 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pDesc)); - if (FunctionIndex >= data.Functions.size()) + if (FunctionIndex >= Data.Functions.size()) return E_INVALIDARG; - const DxcHLSLFunction &func = data.Functions[FunctionIndex]; + const DxcHLSLFunction &func = Data.Functions[FunctionIndex]; LPCSTR name = - data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - ? data.Strings[data.NodeSymbols[func.NodeId].NameId].c_str() + Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + ? Data.Strings[Data.NodeSymbols[func.NodeId].NameId].c_str() : ""; *pDesc = D3D12_HLSL_FUNCTION_DESC{name, func.GetNumParameters(), @@ -246,22 +704,24 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pDesc)); - if (NodeId >= data.Nodes.size()) + if (NodeId >= Data.Nodes.size()) return E_INVALIDARG; - LPCSTR name = - data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - ? data.Strings[data.NodeSymbols[NodeId].NameId].c_str() + LPCSTR name = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + ? Data.Strings[Data.NodeSymbols[NodeId].NameId].c_str() : ""; - const DxcHLSLNode &node = data.Nodes[NodeId]; + const DxcHLSLNode &node = Data.Nodes[NodeId]; *pDesc = D3D12_HLSL_NODE{name, node.GetNodeType(), node.GetLocalId(), - childCountsNonRecursive[NodeId], + ChildCountsNonRecursive[NodeId], node.GetParentId(), - node.GetAnnotationCount()}; + node.GetAnnotationCount(), + node.IsFwdBckDefined() ? node.GetFwdBck() + : uint32_t(-1), + node.IsFwdDeclare()}; return S_OK; } @@ -272,12 +732,12 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pChildNodeId)); - if (NodeId >= data.Nodes.size()) + if (NodeId >= Data.Nodes.size()) return E_INVALIDARG; - auto it = childrenNonRecursive.find(NodeId); + auto it = ChildrenNonRecursive.find(NodeId); - if (it == childrenNonRecursive.end() || ChildId >= it->second.size()) + if (it == ChildrenNonRecursive.end() || ChildId >= it->second.size()) return E_INVALIDARG; *pChildNodeId = it->second[ChildId]; @@ -297,31 +757,60 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex) - (THIS_ _In_ UINT Index) PURE; + (THIS_ _In_ UINT Index) override { + + if (Index >= ConstantBuffers.size()) + return &g_InvalidSRConstantBuffer; + + return &ConstantBuffers[Index]; + } - // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. - STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) - (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE; + //TODO: + //// Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. + //STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) + //(THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE; STDMETHOD(GetStructTypeByIndex) - (THIS_ _In_ UINT StructIndex, - _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + (THIS_ _In_ UINT Index, + _Outptr_ ID3D12ShaderReflectionType **ppType) override { + + IFR(ZeroMemoryToOut(ppType)); + + if (Index >= StructIds.size()) + return E_INVALIDARG; + + *ppType = &Types[StructIds[Index]]; + return S_OK; + } + + STDMETHOD(GetUnionTypeByIndex) + (THIS_ _In_ UINT Index, + _Outptr_ ID3D12ShaderReflectionType **ppType) override { + + IFR(ZeroMemoryToOut(ppType)); + + if (Index >= UnionIds.size()) + return E_INVALIDARG; + + *ppType = &Types[UnionIds[Index]]; + return S_OK; + } STDMETHOD(GetNodeSymbolDesc) (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE_SYMBOL *pDesc) override { IFR(ZeroMemoryToOut(pDesc)); - if (!(data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO)) + if (!(Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO)) return E_UNEXPECTED; - if (NodeId >= data.Nodes.size()) + if (NodeId >= Data.Nodes.size()) return E_INVALIDARG; - const DxcHLSLNodeSymbol &nodeSymbol = data.NodeSymbols[NodeId]; + const DxcHLSLNodeSymbol &nodeSymbol = Data.NodeSymbols[NodeId]; *pDesc = D3D12_HLSL_NODE_SYMBOL{ - data.Strings[data.Sources[nodeSymbol.FileSourceId]].c_str(), + Data.Strings[Data.Sources[nodeSymbol.FileSourceId]].c_str(), nodeSymbol.GetSourceLineStart(), nodeSymbol.SourceLineCount, nodeSymbol.GetSourceColumnStart(), nodeSymbol.GetSourceColumnEnd()}; @@ -330,25 +819,20 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { //Helper for conversion between symbol names - // TODO: GetConstantBufferByIndex - // TODO: GetConstantBufferByName // TODO: GetFunctionParameter - // TODO: GetStructByIndex - // TODO: GetStructTypeByName - // TODO: GetStructTypeByIndex // TODO: types, arrays STDMETHOD(GetNodeByName) (THIS_ _In_ LPCSTR Name, _Out_ UINT *pNodeId) override { - if (!pNodeId) + if (!Name || !pNodeId) return E_POINTER; *pNodeId = (UINT)-1; - auto it = data.FullyResolvedToNodeId.find(Name); + auto it = Data.FullyResolvedToNodeId.find(Name); - if (it == data.FullyResolvedToNodeId.end()) + if (it == Data.FullyResolvedToNodeId.end()) return E_INVALIDARG; *pNodeId = it->second; @@ -385,7 +869,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { UINT nodeId; IFR(GetNodeByName(Name, &nodeId)); - const DxcHLSLNode &node = data.Nodes[nodeId]; + const DxcHLSLNode &node = Data.Nodes[nodeId]; if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER) return E_INVALIDARG; @@ -401,7 +885,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { UINT nodeId; IFR(GetNodeByName(Name, &nodeId)); - const DxcHLSLNode &node = data.Nodes[nodeId]; + const DxcHLSLNode &node = Data.Nodes[nodeId]; if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM) return E_INVALIDARG; @@ -418,7 +902,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { UINT nodeId; IFR(GetNodeByName(Name, &nodeId)); - const DxcHLSLNode &node = data.Nodes[nodeId]; + const DxcHLSLNode &node = Data.Nodes[nodeId]; if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM) return E_INVALIDARG; @@ -447,7 +931,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { UINT nodeId; IFR(GetNodeByName(Name, &nodeId)); - const DxcHLSLNode &node = data.Nodes[nodeId]; + const DxcHLSLNode &node = Data.Nodes[nodeId]; if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION) return E_INVALIDARG; @@ -456,10 +940,60 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByName) - (THIS_ _In_ LPCSTR Name) PURE; + (THIS_ _In_ LPCSTR Name) override { + + if (!Name) + return &g_InvalidSRConstantBuffer; + + auto it = NameToConstantBuffers.find(Name); + + if (it == NameToConstantBuffers.end()) + return &g_InvalidSRConstantBuffer; + + return &ConstantBuffers[it->second]; + } STDMETHOD(GetStructTypeByName) - (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + (THIS_ _In_ LPCSTR Name, + _Outptr_ ID3D12ShaderReflectionType **ppType) override { + + IFR(ZeroMemoryToOut(ppType)); + + if (!Name) + return E_POINTER; + + if (!(Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO)) + return E_INVALIDARG; + + auto it = NameToStructId.find(Name); + + if (it == NameToStructId.end()) + return E_INVALIDARG; + + *ppType = &Types[it->second]; + return S_OK; + } + + STDMETHOD(GetUnionTypeByName) + (THIS_ _In_ LPCSTR Name, + _Outptr_ ID3D12ShaderReflectionType **ppType) override { + + IFR(ZeroMemoryToOut(ppType)); + + if (!Name) + return E_POINTER; + + if (!(Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO)) + return E_INVALIDARG; + + auto it = NameToUnionId.find(Name); + + if (it == NameToUnionId.end()) + return E_INVALIDARG; + + *ppType = &Types[it->second]; + return S_OK; + } }; namespace { @@ -479,6 +1013,21 @@ std::string DefinesToString(DxcDefine *pDefines, UINT32 defineCount) { return defineStr; } +bool IsAbsoluteOrCurDirRelative(const llvm::Twine &T) { + if (llvm::sys::path::is_absolute(T)) { + return true; + } + if (T.isSingleStringRef()) { + StringRef r = T.getSingleStringRef(); + if (r.size() < 2) + return false; + const char *pData = r.data(); + return pData[0] == '.' && (pData[1] == '\\' || pData[1] == '/'); + } + DXASSERT(false, "twine kind not supported"); + return false; +} + void SetupCompilerCommon(CompilerInstance &compiler, DxcLangExtensionsHelper *helper, LPCSTR pMainFile, TextDiagnosticPrinter *diagPrinter, @@ -496,7 +1045,6 @@ void SetupCompilerCommon(CompilerInstance &compiler, // Not use builtin includes. compiler.getHeaderSearchOpts().UseBuiltinIncludes = false; - // apply compiler options applicable for rewrite if (opts.WarningAsError) compiler.getDiagnostics().setWarningsAsErrors(true); compiler.getDiagnostics().setIgnoreAllWarnings(!opts.OutputWarnings); @@ -528,7 +1076,7 @@ void SetupCompilerCommon(CompilerInstance &compiler, for (const llvm::opt::Arg *A : opts.Args.filtered(options::OPT_I)) { const bool IsFrameworkFalse = false; const bool IgnoreSysRoot = true; - if (dxcutil::IsAbsoluteOrCurDirRelative(A->getValue())) { + if (IsAbsoluteOrCurDirRelative(A->getValue())) { HSOpts.AddPath(A->getValue(), frontend::Angled, IsFrameworkFalse, IgnoreSysRoot); } else { @@ -649,11 +1197,11 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, if (opts.RWOpt.ReflectHLSLUserTypes) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES; - if (opts.RWOpt.ReflectHLSLScopes) - reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SCOPES; - - if (opts.RWOpt.ReflectHLSLVariables) - reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_VARIABLES; + //TODO: if (opts.RWOpt.ReflectHLSLScopes) + // reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SCOPES; + // + //TODO: if (opts.RWOpt.ReflectHLSLVariables) + // reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_VARIABLES; if (!opts.RWOpt.ReflectHLSLDisableSymbols) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -712,7 +1260,7 @@ HRESULT ReadOptsAndValidate(hlsl::options::MainArgs &mainArgs, raw_stream_ostream outStream(pOutputStream); if (0 != hlsl::options::ReadDxcOpts(table, - hlsl::options::HlslFlags::RewriteOption, + hlsl::options::HlslFlags::RewriteOption, //TODO: Change to other option mainArgs, opts, outStream)) { CComPtr pErrorBlob; IFT(pOutputStream->QueryInterface(&pErrorBlob)); @@ -859,4 +1407,4 @@ HRESULT CreateDxcReflector(REFIID riid, LPVOID *ppv) { CComPtr isense = DxcReflector::Alloc(DxcGetThreadMallocNoRef()); IFROOM(isense.p); return isense.p->QueryInterface(riid, ppv); -} \ No newline at end of file +} diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 8a13c8c1b2..e0e5be7511 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1084,11 +1084,12 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, if(opts.RWOpt.ReflectHLSLUserTypes) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES; - if(opts.RWOpt.ReflectHLSLScopes) - reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SCOPES; - - if(opts.RWOpt.ReflectHLSLVariables) - reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_VARIABLES; + //TODO: + //if(opts.RWOpt.ReflectHLSLScopes) + // reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SCOPES; + // + //if(opts.RWOpt.ReflectHLSLVariables) + // reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_VARIABLES; if(!opts.RWOpt.ReflectHLSLDisableSymbols) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; From 791d6a7368c8f17070e491756e92d1fc869b255d Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Fri, 19 Sep 2025 23:36:44 +0200 Subject: [PATCH 032/126] Fixed printing forward declarations and the frontend now skips forward declares as if they don't exist. --- include/dxc/DxcReflection/DxcReflection.h | 4 + include/dxc/dxctools.h | 15 +- .../tools/dxcreflection/DxcReflection.cpp | 122 ++++++++------ tools/clang/tools/libclang/dxcreflector.cpp | 156 +++++++++++++----- 4 files changed, 206 insertions(+), 91 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 435e2fa66c..763cdc43fa 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -465,6 +465,10 @@ struct DxcHLSLAnnotation { } }; +//Note: Regarding nodes, node 0 is the root node (global scope) +// If a node is a fwd declare you should inspect the fwd node id. +// If a node isn't a fwd declare but has a backward id, it should be ignored during traversal. +// This node can be defined in a different namespace or type while it's declared elsewhere. struct DxcHLSLReflectionData { D3D12_HLSL_REFLECTION_FEATURE Features{}; diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 8651d7ac4a..aa8d2c37a3 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -173,14 +173,19 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_ENUM, D3D12_HLSL_NODE_TYPE_ENUM_VALUE, D3D12_HLSL_NODE_TYPE_NAMESPACE, - D3D12_HLSL_NODE_TYPE_VARIABLE, // localId points to the type - D3D12_HLSL_NODE_TYPE_TYPEDEF, // ^ - D3D12_HLSL_NODE_TYPE_STRUCT, // has Variables as member like buffers do, localId is unused - D3D12_HLSL_NODE_TYPE_UNION, // ^ + + D3D12_HLSL_NODE_TYPE_VARIABLE, // localId points to the type + D3D12_HLSL_NODE_TYPE_TYPEDEF, // ^ + + D3D12_HLSL_NODE_TYPE_STRUCT, // has Variables as member like buffers do, + // localId is the typeId (if not fwd decl) + D3D12_HLSL_NODE_TYPE_UNION, // ^ + // TODO: D3D12_HLSL_NODE_TYPE_USING, // TODO: D3D12_HLSL_NODE_TYPE_PARAMETER, - D3D12_HLSL_NODE_TYPE_RESERVED = 1 << 7, //Highest bit; reserved as an indicator for fwd declarations + D3D12_HLSL_NODE_TYPE_RESERVED = + 1 << 7, // Highest bit; reserved as an indicator for fwd declarations D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_UNION diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 764010fadf..5c21bc9f14 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1282,10 +1282,17 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (pushObj) { + uint32_t typeId = 0; + + if (isCompleteDefinition) + typeId = GenerateTypeInfo( + ASTCtx, Refl, RecDecl->getASTContext().getRecordType(RecDecl), + DefaultRowMaj); + uint32_t self = PushNextNodeId( Refl, SM, ASTCtx.getLangOpts(), RecDecl->getName(), RecDecl, isStruct ? D3D12_HLSL_NODE_TYPE_STRUCT : D3D12_HLSL_NODE_TYPE_UNION, - ParentNodeId, 0, nullptr, &FwdDecls); + ParentNodeId, typeId, nullptr, &FwdDecls); if (self == uint32_t(-1)) // Duplicate fwd definition continue; @@ -1531,7 +1538,7 @@ static void RecursePrintType(const DxcHLSLReflectionData &Refl, uint32_t TypeId, } uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, - uint32_t Depth, uint32_t IndexInParent) { + uint32_t Depth, uint32_t IndexInParent, bool isThroughFwdDecl = false) { const DxcHLSLNode &node = Refl.Nodes[NodeId]; @@ -1541,11 +1548,18 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - printf("%s%s %s%s\n", std::string(Depth - 1, '\t').c_str(), - NodeTypeToString(node.GetNodeType()).c_str(), - hasSymbols ? Refl.Strings[Refl.NodeSymbols[NodeId].NameId].c_str() - : "(unknown)", - node.IsFwdDeclare() ? " (fwd declare)" : ""); + if (!isThroughFwdDecl) + printf("%s%s %s%s\n", std::string(Depth - 1, '\t').c_str(), + NodeTypeToString(node.GetNodeType()).c_str(), + hasSymbols ? Refl.Strings[Refl.NodeSymbols[NodeId].NameId].c_str() + : "(unknown)", + node.IsFwdDeclare() ? " (declaration)" + : (!isThroughFwdDecl && node.IsFwdBckDefined() + ? " (definition)" + : "")); + + if (node.IsFwdBckDefined() && !node.IsFwdDeclare() && !isThroughFwdDecl) + return node.GetChildCount(); for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) { @@ -1554,63 +1568,63 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, printf(annotation.GetIsBuiltin() ? "%s[%s]\n" : "%s[[%s]]\n", std::string(Depth, '\t').c_str(), - Refl.StringsNonDebug[annotation.GetStringNonDebug()] - .c_str()); + Refl.StringsNonDebug[annotation.GetStringNonDebug()].c_str()); } uint32_t localId = node.GetLocalId(); - switch (node.GetNodeType()) { - - case D3D12_HLSL_NODE_TYPE_REGISTER: { + if (!node.IsFwdDeclare()) + switch (node.GetNodeType()) { - const DxcHLSLRegister ® = Refl.Registers[localId]; + case D3D12_HLSL_NODE_TYPE_REGISTER: { - if (reg.ArrayId == (uint32_t)-1 && reg.BindCount == 1) + const DxcHLSLRegister ® = Refl.Registers[localId]; + + if (reg.ArrayId == (uint32_t)-1 && reg.BindCount == 1) + break; + + printf("%s%s\n", std::string(Depth, '\t').c_str(), + RegisterGetArraySize(Refl, reg).c_str()); break; + } - printf("%s%s\n", - std::string(Depth, '\t').c_str(), - RegisterGetArraySize(Refl, reg).c_str()); - break; - } - - case D3D12_HLSL_NODE_TYPE_UNION: - case D3D12_HLSL_NODE_TYPE_STRUCT: //Children are Variables - break; + case D3D12_HLSL_NODE_TYPE_UNION: + case D3D12_HLSL_NODE_TYPE_STRUCT: // Children are Variables + break; - // TODO: case D3D12_HLSL_NODE_TYPE_USING: + // TODO: case D3D12_HLSL_NODE_TYPE_USING: - case D3D12_HLSL_NODE_TYPE_TYPEDEF: - case D3D12_HLSL_NODE_TYPE_VARIABLE: - typeToPrint = localId; - break; + case D3D12_HLSL_NODE_TYPE_TYPEDEF: + case D3D12_HLSL_NODE_TYPE_VARIABLE: + typeToPrint = localId; + break; - case D3D12_HLSL_NODE_TYPE_FUNCTION: { - const DxcHLSLFunction &func = Refl.Functions[localId]; - printf("%sreturn: %s, hasDefinition: %s, numParams: %u\n", - std::string(Depth, '\t').c_str(), - func.HasReturn() ? "true" : "false", - func.HasDefinition() ? "true" : "false", func.GetNumParameters()); + case D3D12_HLSL_NODE_TYPE_FUNCTION: { + const DxcHLSLFunction &func = Refl.Functions[localId]; + printf("%sreturn: %s, hasDefinition: %s, numParams: %u\n", + std::string(Depth, '\t').c_str(), + func.HasReturn() ? "true" : "false", + func.HasDefinition() ? "true" : "false", + func.GetNumParameters()); - break; - } + break; + } - case D3D12_HLSL_NODE_TYPE_ENUM: - printf("%s: %s\n", std::string(Depth, '\t').c_str(), - EnumTypeToString(Refl.Enums[localId].Type).c_str()); - break; + case D3D12_HLSL_NODE_TYPE_ENUM: + printf("%s: %s\n", std::string(Depth, '\t').c_str(), + EnumTypeToString(Refl.Enums[localId].Type).c_str()); + break; - case D3D12_HLSL_NODE_TYPE_ENUM_VALUE: { - printf("%s#%u = %" PRIi64 "\n", std::string(Depth, '\t').c_str(), - IndexInParent, Refl.EnumValues[localId].Value); + case D3D12_HLSL_NODE_TYPE_ENUM_VALUE: { + printf("%s#%u = %" PRIi64 "\n", std::string(Depth, '\t').c_str(), + IndexInParent, Refl.EnumValues[localId].Value); break; - } + } - case D3D12_HLSL_NODE_TYPE_NAMESPACE: - default: - break; - } + case D3D12_HLSL_NODE_TYPE_NAMESPACE: + default: + break; + } } if (typeToPrint != (uint32_t)-1) @@ -1619,6 +1633,9 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1, j); + if (node.IsFwdDeclare()) + RecursePrint(Refl, node.GetFwdBck(), Depth, IndexInParent, true); + return node.GetChildCount(); } @@ -1843,7 +1860,13 @@ uint32_t RecurseNameGeneration(DxcHLSLReflectionData &Refl, uint32_t NodeId, uint32_t LocalId, const std::string &Parent, bool IsDot) { - const DxcHLSLNode &node = Refl.Nodes[NodeId]; + DxcHLSLNode node = Refl.Nodes[NodeId]; + + if (node.IsFwdDeclare()) { + NodeId = node.GetFwdBck(); + node = Refl.Nodes[NodeId]; + } + std::string self = Refl.Strings[Refl.NodeSymbols[NodeId].NameId]; if (self.empty() && NodeId) @@ -2009,6 +2032,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_STRUCT: case D3D12_HLSL_NODE_TYPE_UNION: allowFwdDeclare = true; + maxValue = node.IsFwdDeclare() ? 1 : header.Types; break; } diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 339a8c3f50..c1edbc425a 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -487,10 +487,18 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { std::vector Types; - std::vector StructIds; - std::vector UnionIds; - std::unordered_map NameToStructId; - std::unordered_map NameToUnionId; + enum class FwdDeclType { + STRUCT, + UNION, + ENUM, + FUNCTION, + COUNT + }; + + std::vector NonFwdIds[int(FwdDeclType::COUNT)]; + + std::unordered_map + NameToNonFwdIds[int(FwdDeclType::COUNT)]; DxcHLSLReflection() = default; @@ -501,17 +509,66 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { ChildCountsNonRecursive.resize(Data.Nodes.size()); ChildrenNonRecursive.clear(); + bool hasSymbols = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + for (uint32_t i = 0; i < uint32_t(Data.Nodes.size()); ++i) { const DxcHLSLNode &node = Data.Nodes[i]; - uint32_t childCount = 0; - for (uint32_t j = 0; j < node.GetChildCount(); ++j, ++childCount) { - ChildrenNonRecursive[i].push_back(i + 1 + j); - j += Data.Nodes[i + 1 + j].GetChildCount(); + //Filter out fwd declarations for structs, unions, functions, enums + + if (!node.IsFwdDeclare()) { + + FwdDeclType type = FwdDeclType::COUNT; + + switch (node.GetNodeType()) { + + case D3D12_HLSL_NODE_TYPE_STRUCT: + type = FwdDeclType::STRUCT; + break; + + case D3D12_HLSL_NODE_TYPE_UNION: + type = FwdDeclType::UNION; + break; + + case D3D12_HLSL_NODE_TYPE_FUNCTION: + type = FwdDeclType::FUNCTION; + break; + + case D3D12_HLSL_NODE_TYPE_ENUM: + type = FwdDeclType::ENUM; + break; + } + + if (type != FwdDeclType::COUNT) { + + uint32_t typeId = node.GetLocalId(); + + NonFwdIds[int(type)].push_back(typeId); + + if (hasSymbols) + NameToNonFwdIds[int(type)] + [Data.Strings[Data.NodeSymbols[i].NameId]] = typeId; + + break; + } + } + + for (uint32_t j = 0; j < node.GetChildCount(); ++j) { + + const DxcHLSLNode &nodej = Data.Nodes[i + 1 + j]; + + //Filter out definitions that were previously fwd declared + //And resolve fwd declarations + + if (nodej.IsFwdDeclare() || !nodej.IsFwdBckDefined()) + ChildrenNonRecursive[i].push_back( + nodej.IsFwdDeclare() ? nodej.GetFwdBck() : i + 1 + j); + + j += nodej.GetChildCount(); } - ChildCountsNonRecursive[i] = childCount; + ChildCountsNonRecursive[i] = uint32_t(ChildrenNonRecursive[i].size()); } NameToConstantBuffers.clear(); @@ -527,11 +584,9 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { ChildrenNonRecursive, &ConstantBuffers[i], Types); - if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + if (hasSymbols) NameToConstantBuffers[ConstantBuffers[i].GetName()] = i; } - - //TODO: Lookup table to struct id and union id } DxcHLSLReflection(DxcHLSLReflectionData &&moved) : Data(moved) { @@ -539,16 +594,19 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } DxcHLSLReflection &operator=(DxcHLSLReflection &&moved) { + Data = std::move(moved.Data); ChildCountsNonRecursive = std::move(moved.ChildCountsNonRecursive); ChildrenNonRecursive = std::move(moved.ChildrenNonRecursive); ConstantBuffers = std::move(moved.ConstantBuffers); NameToConstantBuffers = std::move(moved.NameToConstantBuffers); Types = std::move(moved.Types); - StructIds = std::move(moved.StructIds); - UnionIds = std::move(moved.UnionIds); - NameToStructId = std::move(moved.NameToStructId); - NameToUnionId = std::move(moved.NameToUnionId); + + for (int i = 0; i < int(FwdDeclType::COUNT); ++i) { + NonFwdIds[i] = std::move(moved.NonFwdIds[i]); + NameToNonFwdIds[i] = std::move(moved.NameToNonFwdIds[i]); + } + return *this; } @@ -561,12 +619,12 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { *pDesc = {Data.Features, uint32_t(Data.Buffers.size()), uint32_t(Data.Registers.size()), - uint32_t(Data.Functions.size()), - uint32_t(Data.Enums.size()), + uint32_t(NonFwdIds[int(FwdDeclType::FUNCTION)].size()), + uint32_t(NonFwdIds[int(FwdDeclType::ENUM)].size()), uint32_t(Data.Nodes.size()), uint32_t(Data.Types.size()), - uint32_t(StructIds.size()), - uint32_t(UnionIds.size())}; + uint32_t(NonFwdIds[int(FwdDeclType::STRUCT)].size()), + uint32_t(NonFwdIds[int(FwdDeclType::UNION)].size())}; return S_OK; } @@ -605,14 +663,15 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD(GetEnumDesc) - (THIS_ _In_ UINT EnumIndex, _Out_ D3D12_HLSL_ENUM_DESC* pDesc) override { + (THIS_ _In_ UINT EnumIndex, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) override { IFR(ZeroMemoryToOut(pDesc)); - if (EnumIndex >= Data.Enums.size()) + if (EnumIndex >= NonFwdIds[int(FwdDeclType::ENUM)].size()) return E_INVALIDARG; - const DxcHLSLEnumDesc &enm = Data.Enums[EnumIndex]; + const DxcHLSLEnumDesc &enm = + Data.Enums[NonFwdIds[int(FwdDeclType::ENUM)][EnumIndex]]; LPCSTR name = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO @@ -631,10 +690,10 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pValueDesc)); - if (EnumIndex >= Data.Enums.size()) + if (EnumIndex >= NonFwdIds[int(FwdDeclType::ENUM)].size()) return E_INVALIDARG; - const DxcHLSLEnumDesc &enm = Data.Enums[EnumIndex]; + const DxcHLSLEnumDesc &enm = Data.Enums[NonFwdIds[int(FwdDeclType::ENUM)][EnumIndex]]; const DxcHLSLNode &parent = Data.Nodes[enm.NodeId]; if (ValueIndex >= parent.GetChildCount()) @@ -683,10 +742,11 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(pDesc)); - if (FunctionIndex >= Data.Functions.size()) + if (FunctionIndex >= NonFwdIds[int(FwdDeclType::FUNCTION)].size()) return E_INVALIDARG; - const DxcHLSLFunction &func = Data.Functions[FunctionIndex]; + const DxcHLSLFunction &func = + Data.Functions[NonFwdIds[int(FwdDeclType::FUNCTION)][FunctionIndex]]; LPCSTR name = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO @@ -713,11 +773,24 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { const DxcHLSLNode &node = Data.Nodes[NodeId]; + uint32_t localId = node.GetLocalId(); + uint32_t parentId = node.GetParentId(); + + //Real local id is at definition + + if (node.IsFwdDeclare()) + localId = Data.Nodes[node.GetFwdBck()].GetLocalId(); + + //Real parent is at declaration + + else if(node.IsFwdBckDefined()) + parentId = Data.Nodes[node.GetFwdBck()].GetParentId(); + *pDesc = D3D12_HLSL_NODE{name, node.GetNodeType(), - node.GetLocalId(), + localId, ChildCountsNonRecursive[NodeId], - node.GetParentId(), + parentId, node.GetAnnotationCount(), node.IsFwdBckDefined() ? node.GetFwdBck() : uint32_t(-1), @@ -776,10 +849,10 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(ppType)); - if (Index >= StructIds.size()) + if (Index >= NonFwdIds[int(FwdDeclType::STRUCT)].size()) return E_INVALIDARG; - *ppType = &Types[StructIds[Index]]; + *ppType = &Types[NonFwdIds[int(FwdDeclType::STRUCT)][Index]]; return S_OK; } @@ -789,10 +862,10 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { IFR(ZeroMemoryToOut(ppType)); - if (Index >= UnionIds.size()) + if (Index >= NonFwdIds[int(FwdDeclType::UNION)].size()) return E_INVALIDARG; - *ppType = &Types[UnionIds[Index]]; + *ppType = &Types[NonFwdIds[int(FwdDeclType::UNION)][Index]]; return S_OK; } @@ -887,6 +960,9 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { const DxcHLSLNode &node = Data.Nodes[nodeId]; + if (node.IsFwdDeclare()) + return E_UNEXPECTED; + if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM) return E_INVALIDARG; @@ -904,6 +980,9 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { const DxcHLSLNode &node = Data.Nodes[nodeId]; + if (node.IsFwdDeclare()) + return E_UNEXPECTED; + if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM) return E_INVALIDARG; @@ -933,6 +1012,9 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { const DxcHLSLNode &node = Data.Nodes[nodeId]; + if (node.IsFwdDeclare()) + return E_UNEXPECTED; + if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION) return E_INVALIDARG; @@ -965,9 +1047,9 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (!(Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO)) return E_INVALIDARG; - auto it = NameToStructId.find(Name); + auto it = NameToNonFwdIds[int(FwdDeclType::STRUCT)].find(Name); - if (it == NameToStructId.end()) + if (it == NameToNonFwdIds[int(FwdDeclType::STRUCT)].end()) return E_INVALIDARG; *ppType = &Types[it->second]; @@ -986,9 +1068,9 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (!(Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO)) return E_INVALIDARG; - auto it = NameToUnionId.find(Name); + auto it = NameToNonFwdIds[int(FwdDeclType::UNION)].find(Name); - if (it == NameToUnionId.end()) + if (it == NameToNonFwdIds[int(FwdDeclType::UNION)].end()) return E_INVALIDARG; *ppType = &Types[it->second]; From 884611374e078773cae27abcfc3e5400743d2490 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 20 Sep 2025 13:06:28 +0200 Subject: [PATCH 033/126] Fixed stripping of inner sugar of StructuredBuffer aka would be in the older version. --- .../tools/dxcreflection/DxcReflection.cpp | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 5c21bc9f14..84b4ed6be0 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -895,22 +895,14 @@ static void FillReflectionRegisterAt( case D3D_SIT_UAV_CONSUME_STRUCTURED: case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: { - const RecordType *recordType = Type->getAs(); + const TemplateSpecializationType *templateDesc = + Type->getAs(); - assert(recordType && "Invalid type (not RecordType)"); + assert(templateDesc->getNumArgs() == 1 && + templateDesc->getArg(0).getKind() == TemplateArgument::Type && + "Expected Type"); - const ClassTemplateSpecializationDecl *templateDesc = - dyn_cast(recordType->getDecl()); - - assert(templateDesc && "Invalid template type"); - - const ArrayRef ¶ms = - templateDesc->getTemplateArgs().asArray(); - - assert(params.size() == 1 && - params[0].getKind() == TemplateArgument::Type && "Expected Type"); - - QualType innerType = params[0].getAsType(); + QualType innerType = templateDesc->getArg(0).getAsType(); // The name of the inner struct is $Element if 'array', otherwise equal to // register name From 80f02cee82df23bef383dc308af850d962296617 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 20 Sep 2025 17:58:06 +0200 Subject: [PATCH 034/126] Implemented handling of $Globals in both frontend and backend. --- .../tools/dxcreflection/DxcReflection.cpp | 20 +++++- tools/clang/tools/libclang/dxcreflector.cpp | 64 +++++++++++++++---- 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 84b4ed6be0..87584d00ad 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1237,8 +1237,26 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, type = arr->getElementType(); } - if (!IsHLSLResourceType(type)) + if (!IsHLSLResourceType(type)) { + + VarDecl *varDecl = dyn_cast(it); + + // Handle $Globals + + if (varDecl && Depth == 0 && + varDecl->getStorageClass() != StorageClass::SC_Static) { + + const std::string &name = ValDecl->getName(); + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, ValDecl->getType(), DefaultRowMaj); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, + D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId); + } + continue; + } // TODO: Add Depth > 0 for reflection if // D3D12_HLSL_REFLECTION_FEATURE_SCOPES diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index c1edbc425a..3c5fe839cc 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -347,8 +347,7 @@ class CHLSLReflectionConstantBuffer final protected: const DxcHLSLReflectionData *m_Data; uint32_t m_ChildCount; - uint32_t m_BufferId; - uint32_t m_NodeId; + D3D_CBUFFER_TYPE m_BufferType; std::vector m_Variables; std::unordered_map m_VariablesByName; @@ -359,8 +358,7 @@ class CHLSLReflectionConstantBuffer final public: CHLSLReflectionConstantBuffer() = default; CHLSLReflectionConstantBuffer(CHLSLReflectionConstantBuffer &&other) { - m_BufferId = other.m_BufferId; - m_NodeId = other.m_NodeId; + m_BufferType = other.m_BufferType; m_Data = other.m_Data; m_ChildCount = other.m_ChildCount; std::swap(m_ReflectionName, other.m_ReflectionName); @@ -407,9 +405,8 @@ class CHLSLReflectionConstantBuffer final m_ReflectionName.clear(); m_Data = &Data; - m_NodeId = NodeId; m_ChildCount = uint32_t(children.size()); - m_BufferId = reg.BufferId; + m_BufferType = m_Data->Buffers[reg.BufferId].Type; m_VariablesByName.clear(); m_Variables.resize(children.size()); @@ -433,6 +430,42 @@ class CHLSLReflectionConstantBuffer final } } + //$Globals (only if the global scope contains any VARIABLE node) + void InitializeGlobals(const DxcHLSLReflectionData &Data, + const std::vector &Globals, + CHLSLReflectionConstantBuffer *ConstantBuffer, + std::vector &Types) { + + m_ReflectionName = "$Globals"; + + m_Data = &Data; + m_ChildCount = uint32_t(Globals.size()); + m_BufferType = D3D_CT_CBUFFER; + + m_VariablesByName.clear(); + m_Variables.resize(Globals.size()); + + for (uint32_t i = 0, j = 0; i < m_ChildCount; ++i) { + + uint32_t childId = Globals[i]; + + const DxcHLSLNode &node = Data.Nodes[childId]; + + std::string name; + + if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + name = Data.Strings[Data.NodeSymbols[childId].NameId]; + + uint32_t typeId = Data.Nodes[childId].GetLocalId(); + + m_Variables[i].Initialize(ConstantBuffer, &Types[typeId], + std::move(name)); + + if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + m_VariablesByName[m_Variables[i].GetName()] = i; + } + } + LPCSTR GetName() const { return m_ReflectionName.c_str(); } STDMETHOD(GetDesc)(D3D12_SHADER_BUFFER_DESC *pDesc) override { @@ -440,7 +473,7 @@ class CHLSLReflectionConstantBuffer final IFR(ZeroMemoryToOut(pDesc)); *pDesc = D3D12_SHADER_BUFFER_DESC{ - GetName(), m_Data->Buffers[m_BufferId].Type, m_ChildCount, + GetName(), m_BufferType, m_ChildCount, 0 // TODO: Size when we have it }; @@ -510,12 +543,17 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { ChildrenNonRecursive.clear(); bool hasSymbols = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + std::vector globalVars; for (uint32_t i = 0; i < uint32_t(Data.Nodes.size()); ++i) { const DxcHLSLNode &node = Data.Nodes[i]; - //Filter out fwd declarations for structs, unions, functions, enums + if (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_VARIABLE && + !node.GetParentId()) + globalVars.push_back(i); + + // Filter out fwd declarations for structs, unions, functions, enums if (!node.IsFwdDeclare()) { @@ -558,8 +596,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { const DxcHLSLNode &nodej = Data.Nodes[i + 1 + j]; - //Filter out definitions that were previously fwd declared - //And resolve fwd declarations + // Filter out definitions that were previously fwd declared + // And resolve fwd declarations if (nodej.IsFwdDeclare() || !nodej.IsFwdBckDefined()) ChildrenNonRecursive[i].push_back( @@ -572,7 +610,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } NameToConstantBuffers.clear(); - ConstantBuffers.resize(Data.Buffers.size()); + ConstantBuffers.resize(Data.Buffers.size() + !globalVars.empty()); Types.resize(Data.Types.size()); for (uint32_t i = 0; i < (uint32_t)Data.Types.size(); ++i) @@ -587,6 +625,10 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (hasSymbols) NameToConstantBuffers[ConstantBuffers[i].GetName()] = i; } + + if (globalVars.size()) + ConstantBuffers[Data.Buffers.size()].InitializeGlobals( + Data, globalVars, &ConstantBuffers[Data.Buffers.size()], Types); } DxcHLSLReflection(DxcHLSLReflectionData &&moved) : Data(moved) { From 353ba42c9f1b8f362015f2048b5360958b33d5bb Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 20 Sep 2025 18:10:07 +0200 Subject: [PATCH 035/126] Querying an undefined function is now allowed from the frontend, since it does contain enough data unlike predeclaring struct/union/enum. Now properly handling fwd declares without any implementation --- tools/clang/tools/libclang/dxcreflector.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 3c5fe839cc..a0593f934b 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -599,9 +599,11 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { // Filter out definitions that were previously fwd declared // And resolve fwd declarations - if (nodej.IsFwdDeclare() || !nodej.IsFwdBckDefined()) - ChildrenNonRecursive[i].push_back( - nodej.IsFwdDeclare() ? nodej.GetFwdBck() : i + 1 + j); + if (nodej.IsFwdDeclare() && nodej.IsFwdBckDefined()) + ChildrenNonRecursive[i].push_back(nodej.GetFwdBck()); + + if (!nodej.IsFwdBckDefined()) + ChildrenNonRecursive[i].push_back(i + 1 + j); j += nodej.GetChildCount(); } @@ -820,8 +822,10 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { //Real local id is at definition - if (node.IsFwdDeclare()) - localId = Data.Nodes[node.GetFwdBck()].GetLocalId(); + if (node.IsFwdDeclare()) { + if (node.IsFwdBckDefined()) + localId = Data.Nodes[node.GetFwdBck()].GetLocalId(); + } //Real parent is at declaration @@ -1054,9 +1058,6 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { const DxcHLSLNode &node = Data.Nodes[nodeId]; - if (node.IsFwdDeclare()) - return E_UNEXPECTED; - if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION) return E_INVALIDARG; From 627777d9e0e82227c31c58b7b7a41d67d6e98471 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 20 Sep 2025 20:31:07 +0200 Subject: [PATCH 036/126] Extended D3D12_SHADER_INPUT_BIND_DESC to allow querying multi dimensional array info from resources. Also did the same for types (GetArrayDesc on ID3D12ShaderReflectionType1). --- include/dxc/DxcReflection/DxcReflection.h | 10 +-- include/dxc/dxctools.h | 28 ++++--- .../tools/dxcreflection/DxcReflection.cpp | 8 +- tools/clang/tools/libclang/dxcreflector.cpp | 84 +++++++++++++++---- 4 files changed, 95 insertions(+), 35 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 763cdc43fa..8608ccc82b 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -354,18 +354,18 @@ struct DxcHLSLArray { DxcHLSLArray() = default; DxcHLSLArray(uint32_t ArrayElem, uint32_t ArrayStart) - : ArrayElemStart((ArrayElem << 28) | ArrayStart) { + : ArrayElemStart((ArrayElem << 26) | ArrayStart) { - assert(ArrayElem <= 8 && ArrayElem > 1 && "ArrayElem out of bounds"); - assert(ArrayStart < (1 << 28) && "ArrayStart out of bounds"); + assert(ArrayElem <= 32 && ArrayElem > 1 && "ArrayElem out of bounds"); + assert(ArrayStart < (1 << 26) && "ArrayStart out of bounds"); } bool operator==(const DxcHLSLArray &Other) const { return Other.ArrayElemStart == ArrayElemStart; } - uint32_t ArrayElem() const { return ArrayElemStart >> 28; } - uint32_t ArrayStart() const { return ArrayElemStart << 4 >> 4; } + uint32_t ArrayElem() const { return ArrayElemStart >> 26; } + uint32_t ArrayStart() const { return ArrayElemStart << 6 >> 6; } }; using DxcHLSLMember = uint32_t; //typeId diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index aa8d2c37a3..89a635b0a1 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -13,6 +13,7 @@ #define __DXC_TOOLS__ #include +#include "d3d12shader.h" enum RewriterOptionMask { Default = 0, @@ -210,12 +211,22 @@ struct D3D12_HLSL_NODE_SYMBOL { UINT ColumnEnd; }; -typedef interface ID3D12ShaderReflectionConstantBuffer - ID3D12ShaderReflectionConstantBuffer; +// TODO: Move to d3d12shader.h + +struct D3D12_ARRAY_DESC { + uint32_t ArrayDims; + uint32_t ArrayLengths[32]; // SPV_REFLECT_MAX_ARRAY_DIMS +}; + +struct D3D12_SHADER_INPUT_BIND_DESC1 { + D3D12_SHADER_INPUT_BIND_DESC Desc; + D3D12_ARRAY_DESC ArrayInfo; +}; + +DECLARE_INTERFACE_(ID3D12ShaderReflectionType1, ID3D12ShaderReflectionType) { + STDMETHOD(GetArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC * pArrayDesc) PURE; +}; -typedef struct _D3D12_SHADER_INPUT_BIND_DESC D3D12_SHADER_INPUT_BIND_DESC; -typedef interface ID3D12FunctionParameterReflection ID3D12FunctionParameterReflection; -typedef interface ID3D12ShaderReflectionType ID3D12ShaderReflectionType; typedef interface IDxcHLSLReflection IDxcHLSLReflection; // {7016F834-AE85-4C86-A473-8C2C981DD370} @@ -240,7 +251,7 @@ DECLARE_INTERFACE(IDxcHLSLReflection) { // know the bindings on the backend. STDMETHOD(GetResourceBindingDesc) - (THIS_ _In_ UINT ResourceIndex, _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) + (THIS_ _In_ UINT ResourceIndex, _Out_ D3D12_SHADER_INPUT_BIND_DESC1 *pDesc) PURE; STDMETHOD(GetFunctionDesc) @@ -320,16 +331,13 @@ DECLARE_INTERFACE(IDxcHLSLReflection) { (THIS_ _In_ LPCSTR Name, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) PURE; STDMETHOD(GetResourceBindingDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE; + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_SHADER_INPUT_BIND_DESC1 * pDesc) PURE; STDMETHOD(GetStructTypeByName) (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; STDMETHOD(GetUnionTypeByName) (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; - - STDMETHOD(GetTypeByName) - (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; }; #undef INTERFACE diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 87584d00ad..22c3d9f02e 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -471,8 +471,8 @@ static uint32_t PushArray(DxcHLSLReflectionData &Refl, uint32_t ArraySizeFlat, uint32_t arrayId = uint32_t(Refl.Arrays.size()); uint32_t arrayCountStart = uint32_t(Refl.ArraySizes.size()); - uint32_t numArrayElements = std::min(size_t(8), ArraySize.size()); - assert(Refl.ArraySizes.size() + numArrayElements < ((1 << 28) - 1) && + uint32_t numArrayElements = std::min(size_t(32), ArraySize.size()); + assert(Refl.ArraySizes.size() + numArrayElements < ((1 << 26) - 1) && "Array elements would overflow"); for (uint32_t i = 0; i < ArraySize.size() && i < 8; ++i) { @@ -480,7 +480,7 @@ static uint32_t PushArray(DxcHLSLReflectionData &Refl, uint32_t ArraySizeFlat, uint32_t arraySize = ArraySize[i]; // Flatten rest of array to at least keep consistent array elements - if (i == 7) + if (i == 31) for (uint32_t j = i + 1; j < ArraySize.size(); ++j) arraySize *= ArraySize[j]; @@ -2147,7 +2147,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLArray &arr = Arrays[i]; - if (arr.ArrayElem() <= 1 || arr.ArrayElem() > 8 || + if (arr.ArrayElem() <= 1 || arr.ArrayElem() > 32 || arr.ArrayStart() + arr.ArrayElem() > header.ArraySizes) throw std::invalid_argument("Array " + std::to_string(i) + " points to an invalid array element"); diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index a0593f934b..2319e5ad1f 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -147,7 +147,7 @@ ID3D12ShaderReflectionConstantBuffer *CHLSLInvalidSRVariable::GetBuffer() { class CHLSLReflectionConstantBuffer; -class CHLSLReflectionType final : public ID3D12ShaderReflectionType { +class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { friend class CHLSLReflectionConstantBuffer; protected: @@ -161,6 +161,7 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType { const DxcHLSLReflectionData *m_Data; uint32_t m_TypeId; uint32_t m_Elements; + D3D12_ARRAY_DESC m_ArrayDesc; public: @@ -174,6 +175,15 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType { return S_FALSE; } + STDMETHOD(GetArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) override { + + if (!pArrayDesc) + return E_POINTER; + + *pArrayDesc = m_ArrayDesc; + return S_OK; + } + HRESULT Initialize( const DxcHLSLReflectionData &Data, uint32_t TypeId, std::vector &Types /* Only access < TypeId*/) { @@ -182,6 +192,8 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType { m_Elements = 0; m_Data = &Data; + ZeroMemoryToOut(&m_ArrayDesc); + const DxcHLSLType &type = Data.Types[TypeId]; if (type.IsArray()) { @@ -193,8 +205,18 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType { const DxcHLSLArray &arr = Data.Arrays[type.GetMultiDimensionalArrayId()]; - for (uint32_t i = 0; i < arr.ArrayElem(); ++i) - m_Elements *= Data.ArraySizes[arr.ArrayStart() + i]; + m_ArrayDesc.ArrayDims = arr.ArrayElem(); + + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) { + uint32_t len = Data.ArraySizes[arr.ArrayStart() + i]; + m_Elements *= len; + m_ArrayDesc.ArrayLengths[i] = len; + } + } + + else { + m_ArrayDesc.ArrayDims = 1; + m_ArrayDesc.ArrayLengths[0] = type.Get1DElements(); } } @@ -674,8 +696,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD(GetResourceBindingDesc) - (THIS_ _In_ UINT ResourceIndex, - _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) override { + (THIS_ _In_ UINT ResourceIndex, + _Out_ D3D12_SHADER_INPUT_BIND_DESC1 *pDesc) override { IFR(ZeroMemoryToOut(pDesc)); @@ -689,19 +711,36 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { ? Data.Strings[Data.NodeSymbols[reg.NodeId].NameId].c_str() : ""; - *pDesc = D3D12_SHADER_INPUT_BIND_DESC{ - name, - D3D_SHADER_INPUT_TYPE(reg.Type), - uint32_t(-1), //Invalid bindPoint, depending on backend we might want to change it + if (reg.BindCount > 1) { + + if (reg.ArrayId != uint32_t(-1)) { + + const DxcHLSLArray &arr = Data.Arrays[reg.ArrayId]; + + pDesc->ArrayInfo.ArrayDims = arr.ArrayElem(); + + for (uint32_t i = 0; i < pDesc->ArrayInfo.ArrayDims; ++i) + pDesc->ArrayInfo.ArrayLengths[i] = + Data.ArraySizes[arr.ArrayStart() + i]; + } + + else { + pDesc->ArrayInfo.ArrayDims = 1; + pDesc->ArrayInfo.ArrayLengths[0] = reg.BindCount; + } + } + + pDesc->Desc = D3D12_SHADER_INPUT_BIND_DESC{ + name, D3D_SHADER_INPUT_TYPE(reg.Type), + uint32_t(-1), // Invalid bindPoint, depending on backend we might + // want to change it reg.BindCount, - reg.uFlags, - D3D_RESOURCE_RETURN_TYPE(reg.ReturnType), + reg.uFlags, D3D_RESOURCE_RETURN_TYPE(reg.ReturnType), D3D_SRV_DIMENSION(reg.Dimension), - uint32_t(-1), // Also no valid data depending on backend - uint32_t(-1), //Invalid space (see bindPoint ^) - reg.NodeId - }; + uint32_t(-1), // Also no valid data depending on backend + uint32_t(-1), // Invalid space (see bindPoint ^) + reg.NodeId}; return S_OK; } @@ -884,6 +923,19 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { return &ConstantBuffers[Index]; } + STDMETHOD(GetTypeByIndex) + (THIS_ _In_ UINT Index, + _Outptr_ ID3D12ShaderReflectionType **ppType) override { + + IFR(ZeroMemoryToOut(ppType)); + + if (Index >= Types.size()) + return E_INVALIDARG; + + *ppType = &Types[Index]; + return S_OK; + } + //TODO: //// Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. //STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) @@ -981,7 +1033,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD(GetResourceBindingDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) override { + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_SHADER_INPUT_BIND_DESC1 *pDesc) override { IFR(ZeroMemoryToOut(pDesc)); From bd7e1e36bd0abcf2f83aacc8b9e58774bff2f1ab Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 20 Sep 2025 20:39:41 +0200 Subject: [PATCH 037/126] Now properly ignoring groupshared --- tools/clang/tools/dxcreflection/DxcReflection.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 22c3d9f02e..a69f1d9d87 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1244,7 +1244,8 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, // Handle $Globals if (varDecl && Depth == 0 && - varDecl->getStorageClass() != StorageClass::SC_Static) { + varDecl->getStorageClass() != StorageClass::SC_Static && + !varDecl->hasAttr()) { const std::string &name = ValDecl->getName(); From 4f53503f87e5535c75399554e0dd1950a3c564e2 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 20 Sep 2025 21:26:01 +0200 Subject: [PATCH 038/126] Added dxreflector.exe to be able to spit out a reflection object from CLI. Removed temp reflection code from dxcrewriteunused.cpp. --- include/dxc/Support/HLSLOptions.h | 3 + tools/clang/tools/CMakeLists.txt | 1 + tools/clang/tools/dxreflector/CMakeLists.txt | 40 ++++ tools/clang/tools/dxreflector/dxreflector.cpp | 194 ++++++++++++++++++ tools/clang/tools/dxreflector/dxreflector.rc | 13 ++ .../clang/tools/libclang/dxcrewriteunused.cpp | 62 +----- 6 files changed, 252 insertions(+), 61 deletions(-) create mode 100644 tools/clang/tools/dxreflector/CMakeLists.txt create mode 100644 tools/clang/tools/dxreflector/dxreflector.cpp create mode 100644 tools/clang/tools/dxreflector/dxreflector.rc diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index bfa09f56bd..d3c73a97fc 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -79,6 +79,9 @@ static const unsigned DxcFlags = /// Flags for dxr.exe command-line tool. static const unsigned DxrFlags = HlslFlags::RewriteOption | HlslFlags::DriverOption; +/// Flags for dxreflector.exe command-line tool. +static const unsigned DxreflectorFlags = + HlslFlags::RewriteOption | HlslFlags::DriverOption; /// Flags for IDxcIntelliSense APIs. static const unsigned ISenseFlags = HlslFlags::CoreOption | HlslFlags::ISenseOption; diff --git a/tools/clang/tools/CMakeLists.txt b/tools/clang/tools/CMakeLists.txt index 97e4a8d297..8149beea10 100644 --- a/tools/clang/tools/CMakeLists.txt +++ b/tools/clang/tools/CMakeLists.txt @@ -33,6 +33,7 @@ add_subdirectory(dxa) add_subdirectory(dxopt) add_subdirectory(dxl) add_subdirectory(dxr) +add_subdirectory(dxreflector) add_subdirectory(dxv) # These targets can currently only be built on Windows. diff --git a/tools/clang/tools/dxreflector/CMakeLists.txt b/tools/clang/tools/dxreflector/CMakeLists.txt new file mode 100644 index 0000000000..590fe03c0c --- /dev/null +++ b/tools/clang/tools/dxreflector/CMakeLists.txt @@ -0,0 +1,40 @@ +# Copyright (C) Microsoft Corporation. All rights reserved. +# This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. +# Builds dxreflector.exe + +set( LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + dxcsupport + Option # option library + Support # For Atomic increment/decrement + ) + +add_clang_executable(dxreflector + dxreflector.cpp +# dxreflector.rc + ) + +target_link_libraries(dxreflector + dxclib + dxcompiler + ) + +set_target_properties(dxreflector PROPERTIES VERSION ${CLANG_EXECUTABLE_VERSION}) +# set_target_properties(dxreflector PROPERTIES ENABLE_EXPORTS 1) + +include_directories(${LLVM_SOURCE_DIR}/tools/clang/tools) + +add_dependencies(dxreflector dxclib dxcompiler) + +if(UNIX) + set(CLANGXX_LINK_OR_COPY create_symlink) +# Create a relative symlink + set(dxreflector_binary "dxreflector${CMAKE_EXECUTABLE_SUFFIX}") +else() + set(CLANGXX_LINK_OR_COPY copy) + set(dxreflector_binary "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/dxreflector${CMAKE_EXECUTABLE_SUFFIX}") +endif() + +install(TARGETS dxreflector + RUNTIME DESTINATION bin) + diff --git a/tools/clang/tools/dxreflector/dxreflector.cpp b/tools/clang/tools/dxreflector/dxreflector.cpp new file mode 100644 index 0000000000..334d0739d9 --- /dev/null +++ b/tools/clang/tools/dxreflector/dxreflector.cpp @@ -0,0 +1,194 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// dxreflector.cpp // +// Copyright (C) Microsoft Corporation. All rights reserved. // +// This file is distributed under the University of Illinois Open Source // +// License. See LICENSE.TXT for details. // +// // +// Provides the entry point for the dxreflector console program. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include "dxc/Support/Global.h" +#include "dxc/Support/Unicode.h" +#include "dxc/Support/WinFunctions.h" +#include "dxc/Support/WinIncludes.h" +#include "dxc/Support/microcom.h" +#include "dxclib/dxc.h" +#include +#include + +#include "dxc/Support/HLSLOptions.h" +#include "dxc/Support/WinFunctions.h" +#include "dxc/Support/dxcapi.use.h" +#include "dxc/dxcapi.h" +#include "dxc/dxctools.h" +#include "llvm/Support/raw_ostream.h" + +inline bool wcsieq(LPCWSTR a, LPCWSTR b) { return _wcsicmp(a, b) == 0; } + +using namespace dxc; +using namespace llvm::opt; +using namespace hlsl::options; + +#ifdef _WIN32 +int __cdecl wmain(int argc, const wchar_t **argv_) { +#else +int main(int argc, const char **argv) { + // Convert argv to wchar. + WArgV ArgV(argc, argv); + const wchar_t **argv_ = ArgV.argv(); +#endif + if (FAILED(DxcInitThreadMalloc())) + return 1; + DxcSetThreadMallocToDefault(); + try { + if (initHlslOptTable()) + throw std::bad_alloc(); + + // Parse command line options. + const OptTable *optionTable = getHlslOptTable(); + MainArgs argStrings(argc, argv_); + DxcOpts dxreflectorOpts; + DxcDllSupport dxcSupport; + + // Read options and check errors. + { + std::string errorString; + llvm::raw_string_ostream errorStream(errorString); + int optResult = + ReadDxcOpts(optionTable, DxreflectorFlags, argStrings, dxreflectorOpts, errorStream); + errorStream.flush(); + if (errorString.size()) { + fprintf(stderr, "dxreflector failed : %s\n", errorString.data()); + } + if (optResult != 0) { + return optResult; + } + } + + // Apply defaults. + if (dxreflectorOpts.EntryPoint.empty() && !dxreflectorOpts.RecompileFromBinary) { + dxreflectorOpts.EntryPoint = "main"; + } + + // Setup a helper DLL. + { + std::string dllErrorString; + llvm::raw_string_ostream dllErrorStream(dllErrorString); + int dllResult = SetupDxcDllSupport(dxreflectorOpts, dxcSupport, dllErrorStream); + dllErrorStream.flush(); + if (dllErrorString.size()) { + fprintf(stderr, "%s\n", dllErrorString.data()); + } + if (dllResult) + return dllResult; + } + + EnsureEnabled(dxcSupport); + // Handle help request, which overrides any other processing. + if (dxreflectorOpts.ShowHelp) { + std::string helpString; + llvm::raw_string_ostream helpStream(helpString); + std::string version; + llvm::raw_string_ostream versionStream(version); + WriteDxCompilerVersionInfo( + versionStream, + dxreflectorOpts.ExternalLib.empty() ? (LPCSTR) nullptr + : dxreflectorOpts.ExternalLib.data(), + dxreflectorOpts.ExternalFn.empty() ? (LPCSTR) nullptr + : dxreflectorOpts.ExternalFn.data(), + dxcSupport); + versionStream.flush(); + optionTable->PrintHelp(helpStream, "dxreflector.exe", "DX Reflector", + version.c_str(), hlsl::options::RewriteOption, + (dxreflectorOpts.ShowHelpHidden ? 0 : HelpHidden)); + helpStream.flush(); + WriteUtf8ToConsoleSizeT(helpString.data(), helpString.size()); + return 0; + } + + if (dxreflectorOpts.ShowVersion) { + std::string version; + llvm::raw_string_ostream versionStream(version); + WriteDxCompilerVersionInfo( + versionStream, + dxreflectorOpts.ExternalLib.empty() ? (LPCSTR) nullptr + : dxreflectorOpts.ExternalLib.data(), + dxreflectorOpts.ExternalFn.empty() ? (LPCSTR) nullptr + : dxreflectorOpts.ExternalFn.data(), + dxcSupport); + versionStream.flush(); + WriteUtf8ToConsoleSizeT(version.data(), version.size()); + return 0; + } + + CComPtr pReflector; + CComPtr pRewriteResult; + CComPtr pSource; + std::wstring wName( + CA2W(dxreflectorOpts.InputFile.empty() ? "" : dxreflectorOpts.InputFile.data())); + if (!dxreflectorOpts.InputFile.empty()) + ReadFileIntoBlob(dxcSupport, wName.c_str(), &pSource); + + CComPtr pLibrary; + CComPtr pIncludeHandler; + IFT(dxcSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary)); + IFT(pLibrary->CreateIncludeHandler(&pIncludeHandler)); + IFT(dxcSupport.CreateInstance(CLSID_DxcReflector, &pReflector)); + + IFT(pReflector->FromSource(pSource, wName.c_str(), argv_, argc, + nullptr, 0, pIncludeHandler, + &pRewriteResult)); + + if (dxreflectorOpts.OutputObject.empty()) { + // No -Fo, print to console + WriteOperationResultToConsole(pRewriteResult, !dxreflectorOpts.OutputWarnings); + } else { + WriteOperationErrorsToConsole(pRewriteResult, !dxreflectorOpts.OutputWarnings); + HRESULT hr; + IFT(pRewriteResult->GetStatus(&hr)); + if (SUCCEEDED(hr)) { + CA2W wOutputObject(dxreflectorOpts.OutputObject.data()); + CComPtr pObject; + IFT(pRewriteResult->GetResult(&pObject)); + WriteBlobToFile(pObject, wOutputObject.m_psz, + dxreflectorOpts.DefaultTextCodePage); + } + } + + } catch (const ::hlsl::Exception &hlslException) { + try { + const char *msg = hlslException.what(); + Unicode::acp_char + printBuffer[128]; // printBuffer is safe to treat as UTF-8 because we + // use ASCII contents only + if (msg == nullptr || *msg == '\0') { + sprintf_s(printBuffer, _countof(printBuffer), + "Reflection failed - error code 0x%08x.", hlslException.hr); + msg = printBuffer; + } + + std::string textMessage; + bool lossy; + if (!Unicode::UTF8ToConsoleString(msg, &textMessage, &lossy) || lossy) { + // Do a direct assignment as a last-ditch effort and print out as UTF-8. + textMessage = msg; + } + + printf("%s\n", textMessage.c_str()); + } catch (...) { + printf("Reflection failed - unable to retrieve error message.\n"); + } + + return 1; + } catch (std::bad_alloc &) { + printf("Reflection failed - out of memory.\n"); + return 1; + } catch (...) { + printf("Reflection failed - unable to retrieve error message.\n"); + return 1; + } + + return 0; +} diff --git a/tools/clang/tools/dxreflector/dxreflector.rc b/tools/clang/tools/dxreflector/dxreflector.rc new file mode 100644 index 0000000000..9f2f600e51 --- /dev/null +++ b/tools/clang/tools/dxreflector/dxreflector.rc @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include +#include + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT_UNKNOWN +#define VER_FILEDESCRIPTION_STR "DX Reflector" +#define VER_INTERNALNAME_STR "DX Reflector" +#define VER_ORIGINALFILENAME_STR "dxreflector.exe" + +#include \ No newline at end of file diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index e0e5be7511..8093161416 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -1069,66 +1069,6 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, TranslationUnitDecl *tu = astHelper.tu; - D3D12_HLSL_REFLECTION_FEATURE reflectMask = - D3D12_HLSL_REFLECTION_FEATURE_NONE; - - if(opts.RWOpt.ReflectHLSLBasics) - reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_BASICS; - - if(opts.RWOpt.ReflectHLSLFunctions) - reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS; - - if(opts.RWOpt.ReflectHLSLNamespaces) - reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES; - - if(opts.RWOpt.ReflectHLSLUserTypes) - reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES; - - //TODO: - //if(opts.RWOpt.ReflectHLSLScopes) - // reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SCOPES; - // - //if(opts.RWOpt.ReflectHLSLVariables) - // reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_VARIABLES; - - if(!opts.RWOpt.ReflectHLSLDisableSymbols) - reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - if (reflectMask) { - - //Reflect - - DxcHLSLReflectionData refl(astHelper.compiler, *astHelper.tu, - opts.AutoBindingSpace, reflectMask, - opts.DefaultRowMajor); - - refl.Printf(); - - //Test serialization - - std::vector bytes; - refl.Dump(bytes); - - DxcHLSLReflectionData deserialized(bytes, true); - - assert(deserialized == refl && "Dump or Deserialize doesn't match"); - - printf("Reflection size: %" PRIu64 "\n", bytes.size()); - - //Test stripping symbols - - refl.StripSymbols(); - refl.Printf(); - - refl.Dump(bytes); - - deserialized = DxcHLSLReflectionData(bytes, false); - - assert(deserialized == refl && "Dump or Deserialize doesn't match"); - - printf("Stripped reflection size: %" PRIu64 "\n", bytes.size()); - } - if (opts.RWOpt.SkipStatic && opts.RWOpt.SkipFunctionBody) { // Remove static functions and globals. RemoveStaticDecls(*tu); @@ -1147,7 +1087,7 @@ static HRESULT DoSimpleReWrite(DxcLangExtensionsHelper *pHelper, opts.RWOpt.RemoveUnusedFunctions, w); if (FAILED(hr)) return hr; - } else if (reflectMask & D3D12_HLSL_REFLECTION_FEATURE_BASICS) { + } else { o << "// Rewrite unchanged result:\n"; } From c643880aa3bb3090da11a90a6d8702ad7f8b6b0e Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 21 Sep 2025 00:17:24 +0200 Subject: [PATCH 039/126] Implemented serialization and deserialization from a reflection blob --- tools/clang/tools/libclang/dxcreflector.cpp | 33 +++++++++++---------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 2319e5ad1f..59359fb581 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -248,6 +248,8 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { if (type.BaseClass != uint32_t(-1)) m_pBaseClass = &Types[type.BaseClass]; + + return S_OK; } STDMETHOD(GetDesc)(D3D12_SHADER_TYPE_DESC *pDesc) override { @@ -1545,16 +1547,22 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { CATCH_CPP_RETURN_HRESULT(); } - //TODO: - HRESULT STDMETHODCALLTYPE FromBlob(IDxcBlob *data, IDxcHLSLReflection **ppReflection) override { if (!data || !data->GetBufferSize() || !ppReflection) return E_POINTER; - /* TODO: */ + std::vector bytes((const std::byte *)data->GetBufferPointer(), + (const std::byte *)data->GetBufferPointer() + + data->GetBufferSize()); - return E_FAIL; + try { + DxcHLSLReflectionData deserial(bytes, true); + *ppReflection = new DxcHLSLReflection(std::move(deserial)); + return S_OK; + } catch (...) { + return E_FAIL; + } } HRESULT STDMETHODCALLTYPE ToBlob(IDxcHLSLReflection *reflection, @@ -1563,20 +1571,15 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { if (!reflection || !ppResult) return E_POINTER; - /*TODO: - DxcHLSLReflection *refl = ...; + DxcHLSLReflection *refl = dynamic_cast(reflection); - std::vector bytes; - refl->data.Dump(bytes); + if (!refl) + return E_UNEXPECTED; - library->CreateBlobWithEncodingOnHeapCopy( - vec.data(), // pointer to your data - static_cast(vec.size()), // size in bytes - CP_UTF8, // or 0 for "unknown" - &blob); - */ + std::vector bytes; + refl->Data.Dump(bytes); - return E_FAIL; + return DxcCreateBlobOnHeapCopy(bytes.data(), bytes.size(), ppResult); } }; From f21a204b5b2965be184a634d525aca4e4c71efda Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 21 Sep 2025 21:21:25 +0200 Subject: [PATCH 040/126] Added ReflectOption for dxreflector.exe. Moved all reflection options from rewriter to reflector. --- include/dxc/Support/HLSLOptions.h | 23 +++++--- include/dxc/Support/HLSLOptions.td | 52 +++++++++++-------- lib/DxcSupport/HLSLOptions.cpp | 31 +++++------ tools/clang/tools/dxreflector/dxreflector.cpp | 2 +- tools/clang/tools/libclang/dxcreflector.cpp | 25 +++++---- .../clang/tools/libclang/dxcrewriteunused.cpp | 1 - 6 files changed, 74 insertions(+), 60 deletions(-) diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index d3c73a97fc..6f2cfb2f4e 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -52,6 +52,7 @@ enum HlslFlags { CoreOption = (1 << 15), ISenseOption = (1 << 16), RewriteOption = (1 << 17), + ReflectOption = (1 << 18) }; enum ID { @@ -81,7 +82,7 @@ static const unsigned DxrFlags = HlslFlags::RewriteOption | HlslFlags::DriverOption; /// Flags for dxreflector.exe command-line tool. static const unsigned DxreflectorFlags = - HlslFlags::RewriteOption | HlslFlags::DriverOption; + HlslFlags::ReflectOption | HlslFlags::DriverOption; /// Flags for IDxcIntelliSense APIs. static const unsigned ISenseFlags = HlslFlags::CoreOption | HlslFlags::ISenseOption; @@ -106,13 +107,6 @@ class DxcDefines { struct RewriterOpts { bool Unchanged = false; // OPT_rw_unchanged - bool ReflectHLSLBasics = false; // OPT_rw_reflect_hlsl_basics - bool ReflectHLSLFunctions = false; // OPT_rw_reflect_hlsl_functions - bool ReflectHLSLNamespaces = false; // OPT_rw_reflect_hlsl_namespaces - bool ReflectHLSLUserTypes = false; // OPT_rw_reflect_hlsl_user_types - bool ReflectHLSLScopes = false; // OPT_rw_reflect_hlsl_scopes - bool ReflectHLSLVariables = false; // OPT_rw_reflect_hlsl_variables - bool ReflectHLSLDisableSymbols = false; // OPT_rw_reflect_hlsl_disable_symbols bool SkipFunctionBody = false; // OPT_rw_skip_function_body bool SkipStatic = false; // OPT_rw_skip_static bool GlobalExternByDefault = false; // OPT_rw_global_extern_by_default @@ -124,6 +118,16 @@ struct RewriterOpts { bool DeclGlobalCB = false; // OPT_rw_decl_global_cb }; +struct ReflectOpts { + bool Basics = false; // OPT_reflect_basics + bool Functions = false; // OPT_reflect_functions + bool Namespaces = false; // OPT_reflect_namespaces + bool UserTypes = false; // OPT_reflect_user_types + bool Scopes = false; // OPT_reflect_scopes + bool Variables = false; // OPT_reflect_variables + bool DisableSymbols = false; // OPT_reflect_disable_symbols +}; + /// Use this class to capture all options. class DxcOpts { public: @@ -256,6 +260,9 @@ class DxcOpts { // Rewriter Options RewriterOpts RWOpt; + // Reflector Options + ReflectOpts ReflOpt; + std::vector Warnings; bool IsRootSignatureProfile() const; diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index 9781ad6b2b..07b68eaa75 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -29,6 +29,9 @@ def ISenseOption : OptionFlag; // RewriteOption - This is considered a "rewriter" HLSL option. def RewriteOption : OptionFlag; +// ReflectOption - This is considered a "reflector" HLSL option. +def ReflectOption : OptionFlag; + ////////////////////////////////////////////////////////////////////////////// // Groups @@ -70,6 +73,7 @@ def hlsloptz_Group : OptionGroup<"HLSL Optimization">, HelpText<"Optimization Op def hlslutil_Group : OptionGroup<"HLSL Utility">, HelpText<"Utility Options">; def hlslcore_Group : OptionGroup<"HLSL Core">, HelpText<"Common Options">; def hlslrewrite_Group : OptionGroup<"HLSL Rewriter">, HelpText<"Rewriter Options">; +def hlslreflect_Group : OptionGroup<"HLSL Reflector">, HelpText<"Reflector Options">; def spirv_Group : OptionGroup<"SPIR-V CodeGen">, HelpText<"SPIR-V CodeGen Options">; // SPIRV Change @@ -86,11 +90,11 @@ def spirv_Group : OptionGroup<"SPIR-V CodeGen">, HelpText<"SPIR-V CodeGen Option // The general approach is to include only things that are in use, in the // same order as in Options.td. -def D : JoinedOrSeparate<["-", "/"], "D">, Group, Flags<[CoreOption, RewriteOption]>, +def D : JoinedOrSeparate<["-", "/"], "D">, Group, Flags<[CoreOption, RewriteOption, ReflectOption]>, HelpText<"Define macro">; def H : Flag<["-"], "H">, Flags<[CoreOption]>, Group, HelpText<"Show header includes and nesting depth">; -def I : JoinedOrSeparate<["-", "/"], "I">, Group, Flags<[CoreOption, RewriteOption]>, +def I : JoinedOrSeparate<["-", "/"], "I">, Group, Flags<[CoreOption, RewriteOption, ReflectOption]>, HelpText<"Add directory to include search path">; def O0 : Flag<["-", "/"], "O0">, Group, Flags<[CoreOption]>, HelpText<"Optimization Level 0">; @@ -290,13 +294,13 @@ def pack_optimized : Flag<["-", "/"], "pack-optimized">, Group, HelpText<"Optimize signature packing assuming identical signature provided for each connecting stage">; def pack_optimized_ : Flag<["-", "/"], "pack_optimized">, Group, Flags<[CoreOption, HelpHidden]>, HelpText<"Optimize signature packing assuming identical signature provided for each connecting stage">; -def hlsl_version : Separate<["-", "/"], "HV">, Group, Flags<[CoreOption, RewriteOption]>, +def hlsl_version : Separate<["-", "/"], "HV">, Group, Flags<[CoreOption, RewriteOption, ReflectOption]>, HelpText<"HLSL version (2016, 2017, 2018, 2021). Default is 2021">; -def no_warnings : Flag<["-", "/"], "no-warnings">, Group, Flags<[CoreOption, RewriteOption]>, +def no_warnings : Flag<["-", "/"], "no-warnings">, Group, Flags<[CoreOption, RewriteOption, ReflectOption]>, HelpText<"Suppress warnings">; def rootsig_define : Separate<["-", "/"], "rootsig-define">, Group, Flags<[CoreOption]>, HelpText<"Read root signature from a #define">; -def enable_16bit_types: Flag<["-", "/"], "enable-16bit-types">, Flags<[CoreOption, RewriteOption, DriverOption]>, Group, +def enable_16bit_types: Flag<["-", "/"], "enable-16bit-types">, Flags<[CoreOption, RewriteOption, ReflectOption, DriverOption]>, Group, HelpText<"Enable 16bit types and disable min precision types. Available in HLSL 2018 and shader model 6.2">; def ignore_line_directives : Flag<["-", "/"], "ignore-line-directives">, HelpText<"Ignore line directives">, Flags<[CoreOption]>, Group; def auto_binding_space : Separate<["-", "/"], "auto-binding-space">, Group, Flags<[CoreOption]>, @@ -309,7 +313,7 @@ def default_linkage : Separate<["-", "/"], "default-linkage">, Group; def precise_output : Separate<["-", "/"], "precise-output">, Group, Flags<[CoreOption, HelpHidden]>, HelpText<"Mark output semantic as precise">; -def encoding : Separate<["-", "/"], "encoding">, Group, Flags<[CoreOption, RewriteOption, DriverOption]>, +def encoding : Separate<["-", "/"], "encoding">, Group, Flags<[CoreOption, RewriteOption, ReflectOption, DriverOption]>, HelpText<"Set default encoding for source inputs and text outputs (utf8|utf16(win)|utf32(*nix)|wide) default=utf8">; def validator_version : Separate<["-", "/"], "validator-version">, Group, Flags<[CoreOption, HelpHidden]>, HelpText<"Override validator version for module. Format: ; Default: DXIL.dll version or current internal version.">; @@ -333,9 +337,9 @@ def enable_lifetime_markers : Flag<["-", "/"], "enable-lifetime-markers">, Group HelpText<"Enable generation of lifetime markers">; def disable_lifetime_markers : Flag<["-", "/"], "disable-lifetime-markers">, Group, Flags<[CoreOption, HelpHidden]>, HelpText<"Disable generation of lifetime markers where they would be otherwise (6.6+)">; -def enable_payload_qualifiers : Flag<["-", "/"], "enable-payload-qualifiers">, Group, Flags<[CoreOption, RewriteOption, DriverOption]>, +def enable_payload_qualifiers : Flag<["-", "/"], "enable-payload-qualifiers">, Group, Flags<[CoreOption, RewriteOption, ReflectOption, DriverOption]>, HelpText<"Enables support for payload access qualifiers for raytracing payloads in SM 6.6.">; -def disable_payload_qualifiers : Flag<["-", "/"], "disable-payload-qualifiers">, Group, Flags<[CoreOption, RewriteOption, DriverOption]>, +def disable_payload_qualifiers : Flag<["-", "/"], "disable-payload-qualifiers">, Group, Flags<[CoreOption, RewriteOption, ReflectOption, DriverOption]>, HelpText<"Disables support for payload access qualifiers for raytracing payloads in SM 6.7.">; def disable_exception_handling : Flag<["-", "/"], "disable-exception-handling">, Group, Flags<[DriverOption, HelpHidden]>, HelpText<"Disable dxc handling of exceptions">; @@ -435,7 +439,7 @@ def target_profile : JoinedOrSeparate<["-", "/"], "T">, Flags<[CoreOption]>, Gro // VALRULE-TEXT:BEGIN HelpText<"Set target profile. \n\t: ps_6_0, ps_6_1, ps_6_2, ps_6_3, ps_6_4, ps_6_5, ps_6_6, ps_6_7, ps_6_8, ps_6_9, \n\t\t vs_6_0, vs_6_1, vs_6_2, vs_6_3, vs_6_4, vs_6_5, vs_6_6, vs_6_7, vs_6_8, vs_6_9, \n\t\t gs_6_0, gs_6_1, gs_6_2, gs_6_3, gs_6_4, gs_6_5, gs_6_6, gs_6_7, gs_6_8, gs_6_9, \n\t\t hs_6_0, hs_6_1, hs_6_2, hs_6_3, hs_6_4, hs_6_5, hs_6_6, hs_6_7, hs_6_8, hs_6_9, \n\t\t ds_6_0, ds_6_1, ds_6_2, ds_6_3, ds_6_4, ds_6_5, ds_6_6, ds_6_7, ds_6_8, ds_6_9, \n\t\t cs_6_0, cs_6_1, cs_6_2, cs_6_3, cs_6_4, cs_6_5, cs_6_6, cs_6_7, cs_6_8, cs_6_9, \n\t\t lib_6_1, lib_6_2, lib_6_3, lib_6_4, lib_6_5, lib_6_6, lib_6_7, lib_6_8, lib_6_9, \n\t\t ms_6_5, ms_6_6, ms_6_7, ms_6_8, ms_6_9, \n\t\t as_6_5, as_6_6, as_6_7, as_6_8, as_6_9, \n\t\t ">; // VALRULE-TEXT:END -def entrypoint : JoinedOrSeparate<["-", "/"], "E">, Flags<[CoreOption, RewriteOption]>, Group, +def entrypoint : JoinedOrSeparate<["-", "/"], "E">, Flags<[CoreOption, RewriteOption, ReflectOption]>, Group, HelpText<"Entry point name">; // /I - already defined above def _vi : Flag<["-", "/"], "Vi">, Alias, Flags<[CoreOption]>, Group, @@ -471,7 +475,7 @@ def Gis : Flag<["-", "/"], "Gis">, HelpText<"Force IEEE strictness">, Flags<[Cor def denorm : JoinedOrSeparate<["-", "/"], "denorm">, HelpText<"select denormal value options (any, preserve, ftz). any is the default.">, Flags<[CoreOption]>, Group; -def Fo : JoinedOrSeparate<["-", "/"], "Fo">, MetaVarName<"">, HelpText<"Output object file">, Flags<[CoreOption, RewriteOption, DriverOption]>, Group; +def Fo : JoinedOrSeparate<["-", "/"], "Fo">, MetaVarName<"">, HelpText<"Output object file">, Flags<[CoreOption, RewriteOption, ReflectOption, DriverOption]>, Group; // def Fl : JoinedOrSeparate<["-", "/"], "Fl">, MetaVarName<"">, HelpText<"Output a library">; def Fc : JoinedOrSeparate<["-", "/"], "Fc">, MetaVarName<"">, HelpText<"Output assembly code listing file">, Flags<[DriverOption]>, Group; //def Fx : JoinedOrSeparate<["-", "/"], "Fx">, MetaVarName<"">, HelpText<"Output assembly code and hex listing file">; @@ -562,24 +566,28 @@ def consistent_bindings : Flag<["-", "/"], "consistent-bindings">, Group; ////////////////////////////////////////////////////////////////////////////// -// Rewriter Options +// Reflector Options -def rw_unchanged : Flag<["-", "/"], "unchanged">, Group, Flags<[RewriteOption]>, - HelpText<"Rewrite HLSL, without changes.">; -def rw_reflect_hlsl_basics : Flag<["-", "/"], "reflect-hlsl-basics">, Group, Flags<[RewriteOption]>, - HelpText<"Reflect HLSL (registers, constants and annotations) and generate consistent bindings.">; -def rw_reflect_hlsl_functions : Flag<["-", "/"], "reflect-hlsl-functions">, Group, Flags<[RewriteOption]>, +def reflect_basics : Flag<["-", "/"], "reflect-basics">, Group, Flags<[ReflectOption]>, + HelpText<"Reflect HLSL (registers, constants and annotations).">; +def reflect_functions : Flag<["-", "/"], "reflect-functions">, Group, Flags<[ReflectOption]>, HelpText<"Reflect HLSL functions.">; -def rw_reflect_hlsl_namespaces : Flag<["-", "/"], "reflect-hlsl-namespaces">, Group, Flags<[RewriteOption]>, - HelpText<"Reflect HLSL nodes in namespaces rather than only the root namespace.">; -def rw_reflect_hlsl_user_types : Flag<["-", "/"], "reflect-hlsl-user-types">, Group, Flags<[RewriteOption]>, +def reflect_namespaces : Flag<["-", "/"], "reflect-namespaces">, Group, Flags<[ReflectOption]>, + HelpText<"Reflect HLSL nodes in namespaces rather than only the global namespace.">; +def reflect_user_types : Flag<["-", "/"], "reflect-user-types">, Group, Flags<[ReflectOption]>, HelpText<"Reflect HLSL user types (typedef, using, struct, enum).">; -def rw_reflect_hlsl_scopes : Flag<["-", "/"], "reflect-hlsl-scopes">, Group, Flags<[RewriteOption]>, +def reflect_scopes : Flag<["-", "/"], "reflect-scopes">, Group, Flags<[ReflectOption]>, HelpText<"Reflect HLSL scopes (variables and structs defined in functions, structs and scopes).">; -def rw_reflect_hlsl_variables : Flag<["-", "/"], "reflect-hlsl-variables">, Group, Flags<[RewriteOption]>, +def reflect_variables : Flag<["-", "/"], "reflect-variables">, Group, Flags<[ReflectOption]>, HelpText<"Reflect HLSL static variables.">; -def rw_reflect_hlsl_disable_symbols : Flag<["-", "/"], "reflect-hlsl-disable-symbols">, Group, Flags<[RewriteOption]>, +def reflect_disable_symbols : Flag<["-", "/"], "reflect-disable-symbols">, Group, Flags<[ReflectOption]>, HelpText<"Reflect HLSL disable symbols.">; + +////////////////////////////////////////////////////////////////////////////// +// Rewriter Options + +def rw_unchanged : Flag<["-", "/"], "unchanged">, Group, Flags<[RewriteOption]>, + HelpText<"Rewrite HLSL, without changes.">; def rw_skip_function_body : Flag<["-", "/"], "skip-fn-body">, Group, Flags<[RewriteOption]>, HelpText<"Translate function definitions to declarations">; def rw_skip_static : Flag<["-", "/"], "skip-static">, Group, Flags<[RewriteOption]>, diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index b6d38edd8a..515b819a55 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -1000,7 +1000,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, // XXX TODO: Sort this out, since it's required for new API, but a separate // argument for old APIs. if ((flagsToInclude & hlsl::options::DriverOption) && - !(flagsToInclude & hlsl::options::RewriteOption) && + !(flagsToInclude & (hlsl::options::RewriteOption | hlsl::options::ReflectOption)) && opts.TargetProfile.empty() && !opts.DumpBin && opts.Preprocess.empty() && !opts.RecompileFromBinary) { // Target profile is required in arguments only for drivers when compiling; @@ -1353,20 +1353,6 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, // Rewriter Options if (flagsToInclude & hlsl::options::RewriteOption) { opts.RWOpt.Unchanged = Args.hasFlag(OPT_rw_unchanged, OPT_INVALID, false); - opts.RWOpt.ReflectHLSLBasics = - Args.hasFlag(OPT_rw_reflect_hlsl_basics, OPT_INVALID, false); - opts.RWOpt.ReflectHLSLFunctions = - Args.hasFlag(OPT_rw_reflect_hlsl_functions, OPT_INVALID, false); - opts.RWOpt.ReflectHLSLNamespaces = - Args.hasFlag(OPT_rw_reflect_hlsl_namespaces, OPT_INVALID, false); - opts.RWOpt.ReflectHLSLUserTypes = - Args.hasFlag(OPT_rw_reflect_hlsl_user_types, OPT_INVALID, false); - opts.RWOpt.ReflectHLSLScopes = - Args.hasFlag(OPT_rw_reflect_hlsl_scopes, OPT_INVALID, false); - opts.RWOpt.ReflectHLSLVariables = - Args.hasFlag(OPT_rw_reflect_hlsl_variables, OPT_INVALID, false); - opts.RWOpt.ReflectHLSLDisableSymbols = - Args.hasFlag(OPT_rw_reflect_hlsl_disable_symbols, OPT_INVALID, false); opts.RWOpt.SkipFunctionBody = Args.hasFlag(OPT_rw_skip_function_body, OPT_INVALID, false); opts.RWOpt.SkipStatic = @@ -1395,6 +1381,21 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, } } + if (flagsToInclude & hlsl::options::ReflectOption) { + opts.ReflOpt.Basics = Args.hasFlag(OPT_reflect_basics, OPT_INVALID, false); + opts.ReflOpt.Functions = + Args.hasFlag(OPT_reflect_functions, OPT_INVALID, false); + opts.ReflOpt.Namespaces = + Args.hasFlag(OPT_reflect_namespaces, OPT_INVALID, false); + opts.ReflOpt.UserTypes = + Args.hasFlag(OPT_reflect_user_types, OPT_INVALID, false); + opts.ReflOpt.Scopes = Args.hasFlag(OPT_reflect_scopes, OPT_INVALID, false); + opts.ReflOpt.Variables = + Args.hasFlag(OPT_reflect_variables, OPT_INVALID, false); + opts.ReflOpt.DisableSymbols = + Args.hasFlag(OPT_reflect_disable_symbols, OPT_INVALID, false); + } + opts.Args = std::move(Args); return 0; } diff --git a/tools/clang/tools/dxreflector/dxreflector.cpp b/tools/clang/tools/dxreflector/dxreflector.cpp index 334d0739d9..0ca93d1eaf 100644 --- a/tools/clang/tools/dxreflector/dxreflector.cpp +++ b/tools/clang/tools/dxreflector/dxreflector.cpp @@ -101,7 +101,7 @@ int main(int argc, const char **argv) { dxcSupport); versionStream.flush(); optionTable->PrintHelp(helpStream, "dxreflector.exe", "DX Reflector", - version.c_str(), hlsl::options::RewriteOption, + version.c_str(), hlsl::options::ReflectOption, (dxreflectorOpts.ShowHelpHidden ? 0 : HelpHidden)); helpStream.flush(); WriteUtf8ToConsoleSizeT(helpString.data(), helpString.size()); diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 59359fb581..dc5711a14c 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1228,8 +1228,7 @@ void SetupCompilerCommon(CompilerInstance &compiler, compiler.getDiagnostics().setWarningsAsErrors(true); compiler.getDiagnostics().setIgnoreAllWarnings(!opts.OutputWarnings); compiler.getLangOpts().HLSLVersion = opts.HLSLVersion; - compiler.getLangOpts().PreserveUnknownAnnotations = - opts.RWOpt.ReflectHLSLBasics; + compiler.getLangOpts().PreserveUnknownAnnotations = true; compiler.getLangOpts().UseMinPrecision = !opts.Enable16BitTypes; compiler.getLangOpts().EnableDX9CompatMode = opts.EnableDX9CompatMode; compiler.getLangOpts().EnableFXCCompatMode = opts.EnableFXCCompatMode; @@ -1364,29 +1363,29 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, D3D12_HLSL_REFLECTION_FEATURE reflectMask = D3D12_HLSL_REFLECTION_FEATURE_NONE; - if (opts.RWOpt.ReflectHLSLBasics) + if (opts.ReflOpt.Basics) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_BASICS; - if (opts.RWOpt.ReflectHLSLFunctions) + if (opts.ReflOpt.Functions) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS; - if (opts.RWOpt.ReflectHLSLNamespaces) + if (opts.ReflOpt.Namespaces) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES; - if (opts.RWOpt.ReflectHLSLUserTypes) + if (opts.ReflOpt.UserTypes) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES; - //TODO: if (opts.RWOpt.ReflectHLSLScopes) + //TODO: if (opts.ReflOpt.Scopes) // reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SCOPES; // - //TODO: if (opts.RWOpt.ReflectHLSLVariables) + //TODO: if (opts.ReflOpt.Variables) // reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_VARIABLES; - if (!opts.RWOpt.ReflectHLSLDisableSymbols) - reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (!reflectMask) - reflectMask = D3D12_HLSL_REFLECTION_FEATURE_ALL; + reflectMask = D3D12_HLSL_REFLECTION_FEATURE_ALL; + + if (!opts.ReflOpt.DisableSymbols) + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; DxcHLSLReflectionData refl(astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, reflectMask, @@ -1439,7 +1438,7 @@ HRESULT ReadOptsAndValidate(hlsl::options::MainArgs &mainArgs, raw_stream_ostream outStream(pOutputStream); if (0 != hlsl::options::ReadDxcOpts(table, - hlsl::options::HlslFlags::RewriteOption, //TODO: Change to other option + hlsl::options::HlslFlags::ReflectOption, mainArgs, opts, outStream)) { CComPtr pErrorBlob; IFT(pOutputStream->QueryInterface(&pErrorBlob)); diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 8093161416..64fa2dde22 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -543,7 +543,6 @@ void SetupCompilerCommon(CompilerInstance &compiler, compiler.getDiagnostics().setWarningsAsErrors(true); compiler.getDiagnostics().setIgnoreAllWarnings(!opts.OutputWarnings); compiler.getLangOpts().HLSLVersion = opts.HLSLVersion; - compiler.getLangOpts().PreserveUnknownAnnotations = opts.RWOpt.ReflectHLSLBasics; compiler.getLangOpts().UseMinPrecision = !opts.Enable16BitTypes; compiler.getLangOpts().EnableDX9CompatMode = opts.EnableDX9CompatMode; compiler.getLangOpts().EnableFXCCompatMode = opts.EnableFXCCompatMode; From 0248f29d6d337bab36ee74d9cc9e8533416db223 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 21 Sep 2025 21:33:12 +0200 Subject: [PATCH 041/126] Removed unused variables from setup in dxreflector.exe. -D now properly works with dxreflector --- tools/clang/tools/libclang/dxcreflector.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index dc5711a14c..10d86e91cf 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1226,12 +1226,9 @@ void SetupCompilerCommon(CompilerInstance &compiler, if (opts.WarningAsError) compiler.getDiagnostics().setWarningsAsErrors(true); - compiler.getDiagnostics().setIgnoreAllWarnings(!opts.OutputWarnings); compiler.getLangOpts().HLSLVersion = opts.HLSLVersion; compiler.getLangOpts().PreserveUnknownAnnotations = true; compiler.getLangOpts().UseMinPrecision = !opts.Enable16BitTypes; - compiler.getLangOpts().EnableDX9CompatMode = opts.EnableDX9CompatMode; - compiler.getLangOpts().EnableFXCCompatMode = opts.EnableFXCCompatMode; compiler.getDiagnostics().setIgnoreAllWarnings(!opts.OutputWarnings); compiler.getCodeGenOpts().MainFileName = pMainFile; @@ -1245,8 +1242,6 @@ void SetupCompilerCommon(CompilerInstance &compiler, PPOpts.RemappedFilesKeepOriginalName = true; } - PPOpts.ExpandTokPastingArg = opts.LegacyMacroExpansion; - // Pick additional arguments. clang::HeaderSearchOptions &HSOpts = compiler.getHeaderSearchOpts(); HSOpts.UseBuiltinIncludes = 0; @@ -1286,6 +1281,15 @@ void SetupCompiler(CompilerInstance &compiler, compiler.getPreprocessor().setPredefines(newDefines); } + if (opts.Defines.size()) { + + std::string defines = + DefinesToString(opts.Defines.DefineVector.data(), opts.Defines.size()); + + compiler.getPreprocessor().setPredefines( + compiler.getPreprocessor().getPredefines() + defines); + } + compiler.createASTContext(); compiler.setASTConsumer(std::unique_ptr(new SemaConsumer())); compiler.createSema(TU_Complete, nullptr); From d728f73c32271a7a483e4bd114c5931b81c8942c Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 21 Sep 2025 21:58:11 +0200 Subject: [PATCH 042/126] Fixed implicit functions causing problems with ->getName() --- tools/clang/tools/dxcreflection/DxcReflection.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index a69f1d9d87..96900d552c 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1093,6 +1093,9 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS)) continue; + if (Func->isImplicit()) + continue; + const FunctionDecl *Definition = nullptr; uint32_t nodeId = From 0ae49a481d9132b69f1b967a062b13d333d70b26 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 22 Sep 2025 22:01:27 +0200 Subject: [PATCH 043/126] Added ability to specify -T with the dxreflector.exe, in case -enable-16bit-types is used or anything that needs a specific target. Fixed an issue with recursive types. --- include/dxc/Support/HLSLOptions.td | 2 +- .../tools/dxcreflection/DxcReflection.cpp | 38 ++++++++++++++----- tools/clang/tools/libclang/dxcreflector.cpp | 2 + 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index 07b68eaa75..4353fde033 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -434,7 +434,7 @@ def fvk_bind_counter_heap : MultiArg<["-"], "fvk-bind-counter-heap", 2>, MetaVar ////////////////////////////////////////////////////////////////////////////// // fxc-based flags that don't match those previously defined. -def target_profile : JoinedOrSeparate<["-", "/"], "T">, Flags<[CoreOption]>, Group, MetaVarName<"">, +def target_profile : JoinedOrSeparate<["-", "/"], "T">, Flags<[CoreOption, ReflectOption]>, Group, MetaVarName<"">, /* hctdb_instrhelp.get_target_profiles()*/ // VALRULE-TEXT:BEGIN HelpText<"Set target profile. \n\t: ps_6_0, ps_6_1, ps_6_2, ps_6_3, ps_6_4, ps_6_5, ps_6_6, ps_6_7, ps_6_8, ps_6_9, \n\t\t vs_6_0, vs_6_1, vs_6_2, vs_6_3, vs_6_4, vs_6_5, vs_6_6, vs_6_7, vs_6_8, vs_6_9, \n\t\t gs_6_0, gs_6_1, gs_6_2, gs_6_3, gs_6_4, gs_6_5, gs_6_6, gs_6_7, gs_6_8, gs_6_9, \n\t\t hs_6_0, hs_6_1, hs_6_2, hs_6_3, hs_6_4, hs_6_5, hs_6_6, hs_6_7, hs_6_8, hs_6_9, \n\t\t ds_6_0, ds_6_1, ds_6_2, ds_6_3, ds_6_4, ds_6_5, ds_6_6, ds_6_7, ds_6_8, ds_6_9, \n\t\t cs_6_0, cs_6_1, cs_6_2, cs_6_3, cs_6_4, cs_6_5, cs_6_6, cs_6_7, cs_6_8, cs_6_9, \n\t\t lib_6_1, lib_6_2, lib_6_3, lib_6_4, lib_6_5, lib_6_6, lib_6_7, lib_6_8, lib_6_9, \n\t\t ms_6_5, ms_6_6, ms_6_7, ms_6_8, ms_6_9, \n\t\t as_6_5, as_6_6, as_6_7, as_6_8, as_6_9, \n\t\t ">; diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 96900d552c..e629db97cf 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -681,6 +681,8 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, // Inner types + // Reserve member names and types + for (Decl *decl : recordDecl->decls()) { FieldDecl *fieldDecl = dyn_cast(decl); @@ -688,23 +690,39 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, if (!fieldDecl) continue; - QualType original = fieldDecl->getType(); + if (!membersCount) + membersOffset = (uint32_t)Refl.MemberTypeIds.size(); + std::string name = fieldDecl->getName(); - uint32_t nameId = hasSymbols ? RegisterString(Refl, name, false) : uint32_t(-1); - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); + uint32_t nameId = + hasSymbols ? RegisterString(Refl, name, false) : uint32_t(-1); - if (!membersCount) - membersOffset = (uint32_t) Refl.MemberTypeIds.size(); + if (hasSymbols) + Refl.MemberNameIds.push_back(nameId); + + ++membersCount; + } + + if (membersCount) + Refl.MemberTypeIds.resize(Refl.MemberTypeIds.size() + membersCount); + + // Initialize member types (because it causes recursion) + + membersCount = 0; + + for (Decl *decl : recordDecl->decls()) { + + FieldDecl *fieldDecl = dyn_cast(decl); + + if (!fieldDecl) + continue; assert(Refl.MemberTypeIds.size() <= (uint32_t)-1 && "Members out of bounds"); - Refl.MemberTypeIds.push_back(typeId); - - if (hasSymbols) - Refl.MemberNameIds.push_back(nameId); + Refl.MemberTypeIds[membersOffset + membersCount] = + GenerateTypeInfo(ASTCtx, Refl, fieldDecl->getType(), DefaultRowMaj); ++membersCount; } diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 10d86e91cf..2349e2e127 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1231,6 +1231,8 @@ void SetupCompilerCommon(CompilerInstance &compiler, compiler.getLangOpts().UseMinPrecision = !opts.Enable16BitTypes; compiler.getDiagnostics().setIgnoreAllWarnings(!opts.OutputWarnings); compiler.getCodeGenOpts().MainFileName = pMainFile; + compiler.getLangOpts().HLSLProfile = compiler.getCodeGenOpts().HLSLProfile = + opts.TargetProfile; PreprocessorOptions &PPOpts = compiler.getPreprocessorOpts(); if (rewrite != nullptr) { From ec241f86d2475bdc228a4faca08d44a1ca80f1f9 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Fri, 26 Sep 2025 22:09:01 +0200 Subject: [PATCH 044/126] Removed reflect-variables from dxreflector. Implemented static variables. --- include/dxc/DxcReflection/DxcReflection.h | 2 +- include/dxc/Support/HLSLOptions.h | 1 - include/dxc/Support/HLSLOptions.td | 2 - include/dxc/dxctools.h | 7 ++- lib/DxcSupport/HLSLOptions.cpp | 2 - .../tools/dxcreflection/DxcReflection.cpp | 43 ++++++++++++------- tools/clang/tools/libclang/dxcreflector.cpp | 3 -- 7 files changed, 31 insertions(+), 29 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 8608ccc82b..6a24ce9aa4 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -119,7 +119,7 @@ class DxcHLSLNode { assert(DefinitionId < ((1 << 24) - 1) && "DefinitionId out of bounds"); assert(DefinitionId != SelfId && "NodeId can't be definition id!"); assert(IsFwdDeclare() && - "Can't run ResolveFwdDeclare on a node that's one"); + "Can't run ResolveFwdDeclare on a node that's no fwd decl"); assert(!Definition.IsFwdBckDefined() && !IsFwdBckDefined() && "Fwd & backward declare must not be defined yet"); diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index 6f2cfb2f4e..569bc8d16f 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -124,7 +124,6 @@ struct ReflectOpts { bool Namespaces = false; // OPT_reflect_namespaces bool UserTypes = false; // OPT_reflect_user_types bool Scopes = false; // OPT_reflect_scopes - bool Variables = false; // OPT_reflect_variables bool DisableSymbols = false; // OPT_reflect_disable_symbols }; diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index 4353fde033..5a68f53c6b 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -578,8 +578,6 @@ def reflect_user_types : Flag<["-", "/"], "reflect-user-types">, Group; def reflect_scopes : Flag<["-", "/"], "reflect-scopes">, Group, Flags<[ReflectOption]>, HelpText<"Reflect HLSL scopes (variables and structs defined in functions, structs and scopes).">; -def reflect_variables : Flag<["-", "/"], "reflect-variables">, Group, Flags<[ReflectOption]>, - HelpText<"Reflect HLSL static variables.">; def reflect_disable_symbols : Flag<["-", "/"], "reflect-disable-symbols">, Group, Flags<[ReflectOption]>, HelpText<"Reflect HLSL disable symbols.">; diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 89a635b0a1..e99c8f5880 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -93,9 +93,6 @@ enum D3D12_HLSL_REFLECTION_FEATURE { // Variables, structs, functions defined in functions, scopes & structs //TODO: D3D12_HLSL_REFLECTION_FEATURE_SCOPES = 1 << 4, - // Variables not included in $Global or cbuffers - //TODO: D3D12_HLSL_REFLECTION_FEATURE_VARIABLES = 1 << 5, - // Symbol info (stripping this will remove names and file location info) D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO = 1 << 16, @@ -182,6 +179,8 @@ enum D3D12_HLSL_NODE_TYPE { // localId is the typeId (if not fwd decl) D3D12_HLSL_NODE_TYPE_UNION, // ^ + D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE, + // TODO: D3D12_HLSL_NODE_TYPE_USING, // TODO: D3D12_HLSL_NODE_TYPE_PARAMETER, @@ -189,7 +188,7 @@ enum D3D12_HLSL_NODE_TYPE { 1 << 7, // Highest bit; reserved as an indicator for fwd declarations D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_UNION + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE }; struct D3D12_HLSL_NODE { diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index 515b819a55..99415c9c75 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -1390,8 +1390,6 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, opts.ReflOpt.UserTypes = Args.hasFlag(OPT_reflect_user_types, OPT_INVALID, false); opts.ReflOpt.Scopes = Args.hasFlag(OPT_reflect_scopes, OPT_INVALID, false); - opts.ReflOpt.Variables = - Args.hasFlag(OPT_reflect_variables, OPT_INVALID, false); opts.ReflOpt.DisableSymbols = Args.hasFlag(OPT_reflect_disable_symbols, OPT_INVALID, false); } diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index e629db97cf..b771125880 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1242,16 +1242,30 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) continue; - //TODO: Handle values if D3D12_HLSL_REFLECTION_FEATURE_VARIABLES + VarDecl *varDecl = dyn_cast(it); - //ValDecl->print(pfStream); + if (varDecl && varDecl->getStorageClass() == StorageClass::SC_Static && + !varDecl->hasAttr()) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + const std::string &name = ValDecl->getName(); + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, ValDecl->getType(), DefaultRowMaj); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, + D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE, ParentNodeId, typeId); + + continue; + } uint32_t arraySize = 1; QualType type = ValDecl->getType(); std::vector arrayElem; - while (const ConstantArrayType *arr = - dyn_cast(type)) { + while (const ConstantArrayType *arr = dyn_cast(type)) { uint32_t current = arr->getSize().getZExtValue(); arrayElem.push_back(current); arraySize *= arr->getSize().getZExtValue(); @@ -1260,13 +1274,9 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!IsHLSLResourceType(type)) { - VarDecl *varDecl = dyn_cast(it); - // Handle $Globals - if (varDecl && Depth == 0 && - varDecl->getStorageClass() != StorageClass::SC_Static && - !varDecl->hasAttr()) { + if (varDecl && Depth == 0 && !varDecl->hasAttr()) { const std::string &name = ValDecl->getName(); @@ -1280,9 +1290,6 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, continue; } - // TODO: Add Depth > 0 for reflection if - // D3D12_HLSL_REFLECTION_FEATURE_SCOPES - if (Depth != 0) continue; @@ -1407,9 +1414,9 @@ static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { - static const char *arr[] = {"Register", "Function", "Enum", - "EnumValue", "Namespace", "Variable", - "Typedef", "Struct", "Union"}; + static const char *arr[] = { + "Register", "Function", "Enum", "EnumValue", "Namespace", + "Variable", "Typedef", "Struct", "Union", "StaticVariable"}; return arr[uint32_t(type)]; } @@ -1628,6 +1635,7 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: + case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: typeToPrint = localId; break; @@ -1909,7 +1917,9 @@ uint32_t RecurseNameGeneration(DxcHLSLReflectionData &Refl, uint32_t NodeId, Refl.NodeIdToFullyResolved[NodeId] = self; bool isDotChild = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_REGISTER; - bool isVar = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_VARIABLE; + + bool isVar = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_VARIABLE || + node.GetNodeType() == D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE; for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) i += RecurseNameGeneration(Refl, NodeId + 1 + i, j, self, isDotChild); @@ -2058,6 +2068,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes // TODO: case D3D12_HLSL_NODE_TYPE_USING: case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: + case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: maxValue = header.Types; break; diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 2349e2e127..471cee972e 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1383,9 +1383,6 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, //TODO: if (opts.ReflOpt.Scopes) // reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SCOPES; - // - //TODO: if (opts.ReflOpt.Variables) - // reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_VARIABLES; if (!reflectMask) reflectMask = D3D12_HLSL_REFLECTION_FEATURE_ALL; From bf0c4625ff8bce56119a4715c3ecc99e118e8081 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Fri, 26 Sep 2025 23:08:22 +0200 Subject: [PATCH 045/126] Added semanticId to DxcHLSLNode, this points to a non debug string that gets preserved even if symbols are stripped (like annotations). This allows querying semantics even on types that don't expose semantics at DXIL level. --- include/dxc/DxcReflection/DxcReflection.h | 14 +++++++-- include/dxc/dxctools.h | 1 + .../tools/dxcreflection/DxcReflection.cpp | 30 +++++++++++++++++-- tools/clang/tools/libclang/dxcreflector.cpp | 6 ++++ 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 6a24ce9aa4..d7b375364b 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -49,6 +49,9 @@ class DxcHLSLNode { }; }; + uint16_t SemanticId; + uint16_t Padding; + void SetFwdBck(uint32_t v) { FwdBckHi = v >> 8; ChildCountFwdBckLo &= 0xFFFFFF; @@ -61,11 +64,11 @@ class DxcHLSLNode { DxcHLSLNode(D3D12_HLSL_NODE_TYPE NodeType, bool IsFwdDeclare, uint32_t LocalId, uint16_t AnnotationStart, uint32_t ChildCount, - uint32_t ParentId, uint8_t AnnotationCount) + uint32_t ParentId, uint8_t AnnotationCount, uint16_t SemanticId) : LocalIdParentLo(LocalId | (ParentId << 24)), ParentHi(ParentId >> 8), Annotations(AnnotationCount), Type(NodeType), ChildCountFwdBckLo(ChildCount | (0xFFu << 24)), FwdBckHi(0xFFFF), - AnnotationStart(AnnotationStart) { + AnnotationStart(AnnotationStart), SemanticId(SemanticId), Padding(0) { assert(NodeType >= D3D12_HLSL_NODE_TYPE_START && NodeType <= D3D12_HLSL_NODE_TYPE_END && "Invalid enum value"); @@ -132,6 +135,10 @@ class DxcHLSLNode { uint32_t GetLocalId() const { return LocalIdParentLo << 8 >> 8; } uint32_t GetAnnotationStart() const { return AnnotationStart; } + uint32_t GetSemanticId() const { + return SemanticId == uint16_t(-1) ? uint32_t(-1) : SemanticId; + } + D3D12_HLSL_NODE_TYPE GetNodeType() const { return D3D12_HLSL_NODE_TYPE(Type & 0x7F); } @@ -154,7 +161,8 @@ class DxcHLSLNode { return LocalIdParentLo == other.LocalIdParentLo && ParentHiAnnotationsType32 == other.ParentHiAnnotationsType32 && ChildCountFwdBckLo == other.ChildCountFwdBckLo && - AnnotationStartFwdBckHi == other.AnnotationStartFwdBckHi; + AnnotationStartFwdBckHi == other.AnnotationStartFwdBckHi && + SemanticId == other.SemanticId; } }; diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index e99c8f5880..7aa8cba5c6 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -193,6 +193,7 @@ enum D3D12_HLSL_NODE_TYPE { struct D3D12_HLSL_NODE { LPCSTR Name; + LPCSTR Semantic; D3D12_HLSL_NODE_TYPE Type; UINT LocalId; UINT ChildCount; diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index b771125880..026f91b7bb 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -80,6 +80,8 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, uint16_t annotationStart = uint16_t(Refl.Annotations.size()); uint8_t annotationCount = 0; + uint16_t semanticId = uint16_t(-1); + if (DeclSelf) { for (const Attr *attr : DeclSelf->attrs()) { if (const AnnotateAttr *annotate = dyn_cast(attr)) { @@ -107,8 +109,21 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, assert(annotationCount != uint8_t(-1) && "Annotation count out of bounds"); ++annotationCount; + } } + + if (ValueDecl *valDecl = dyn_cast(DeclSelf)) { + + const ArrayRef &UA = + valDecl->getUnusualAnnotations(); + + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) + if ((*It)->getKind() == hlsl::UnusualAnnotation::UA_SemanticDecl) { + semanticId = RegisterString( + Refl, cast(*It)->SemanticName.str(), true); + } + } } bool isFwdDeclare = false; @@ -155,7 +170,8 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, } Refl.Nodes.push_back(DxcHLSLNode{Type, isFwdDeclare, LocalId, annotationStart, - 0, ParentNodeId, annotationCount}); + 0, ParentNodeId, annotationCount, + semanticId}); if (Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { @@ -1377,8 +1393,8 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(clang::CompilerInstance &Compiler, NodeSymbols.push_back(DxcHLSLNodeSymbol(0, 0, 0, 0, 0, 0)); } - Nodes.push_back( - DxcHLSLNode{D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, 0, 0, 0xFFFF, 0}); + Nodes.push_back(DxcHLSLNode{D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, 0, 0, + 0xFFFF, 0, uint16_t(-1)}); std::unordered_map fwdDecls; RecursiveReflectHLSL(Ctx, Compiler.getASTContext(), Diags, SM, *this, @@ -1610,6 +1626,10 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, Refl.StringsNonDebug[annotation.GetStringNonDebug()].c_str()); } + if (node.GetSemanticId() != uint32_t(-1)) + printf("%s: %s\n", std::string(Depth, '\t').c_str(), + Refl.StringsNonDebug[node.GetSemanticId()].c_str()); + uint32_t localId = node.GetLocalId(); if (!node.IsFwdDeclare()) @@ -2046,6 +2066,10 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes i + node.GetChildCount() > header.Nodes) throw std::invalid_argument("Node " + std::to_string(i) + " is invalid"); + if (node.GetSemanticId() != uint32_t(-1) && + node.GetSemanticId() >= header.StringsNonDebug) + throw std::invalid_argument("Node " + std::to_string(i) + " points to invalid semantic id"); + uint32_t maxValue = 1; bool allowFwdDeclare = false; diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 471cee972e..5c3bb6a192 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -873,7 +873,13 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { else if(node.IsFwdBckDefined()) parentId = Data.Nodes[node.GetFwdBck()].GetParentId(); + LPCSTR semantic = ""; + + if (node.GetSemanticId() != uint32_t(-1)) + semantic = Data.StringsNonDebug[node.GetSemanticId()].c_str(); + *pDesc = D3D12_HLSL_NODE{name, + semantic, node.GetNodeType(), localId, ChildCountsNonRecursive[NodeId], From 98e86b50539baec2f7c4018196c7fe062d5474fc Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 27 Sep 2025 15:12:34 +0200 Subject: [PATCH 046/126] Interfaces support: DxcHLSLType can now properly point to interfaces. Added a way to query interfaces by name and id. --- include/dxc/DxcReflection/DxcReflection.h | 55 ++--- include/dxc/dxctools.h | 12 +- .../tools/dxcreflection/DxcReflection.cpp | 191 +++++++++++++++--- tools/clang/tools/libclang/dxcreflector.cpp | 72 ++++++- 4 files changed, 264 insertions(+), 66 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index d7b375364b..b86ad8019c 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -376,39 +376,43 @@ struct DxcHLSLArray { uint32_t ArrayStart() const { return ArrayElemStart << 6 >> 6; } }; -using DxcHLSLMember = uint32_t; //typeId - struct DxcHLSLType { // Almost maps to CShaderReflectionType and // D3D12_SHADER_TYPE_DESC, but tightly packed and // easily serializable + + uint32_t MemberData; // 24 : 8 (start, count) + union { struct { - uint32_t MemberData; //24 : 8 (start, count) - uint8_t Class; // D3D_SHADER_VARIABLE_CLASS - uint8_t Type; // D3D_SHADER_VARIABLE_TYPE + uint8_t Class; // D3D_SHADER_VARIABLE_CLASS + uint8_t Type; // D3D_SHADER_VARIABLE_TYPE uint8_t Rows; uint8_t Columns; }; - uint64_t MemberDataClassTypeRowsColums; + uint32_t ClassTypeRowsColums; }; - union { - struct { - uint32_t ElementsOrArrayId; - uint32_t BaseClass; // -1 if none, otherwise a type index - }; - uint64_t ElementsOrArrayIdBaseClass; - }; + uint32_t ElementsOrArrayId; + uint32_t BaseClass; // -1 if none, otherwise a type index + + uint32_t InterfaceOffsetAndCount; // 24 : 8 (start, count) bool operator==(const DxcHLSLType &Other) const { - return Other.MemberDataClassTypeRowsColums == - MemberDataClassTypeRowsColums && - ElementsOrArrayIdBaseClass == Other.ElementsOrArrayIdBaseClass; + return Other.MemberData == MemberData && + Other.ElementsOrArrayId == ElementsOrArrayId && + ClassTypeRowsColums == Other.ClassTypeRowsColums && + BaseClass == Other.BaseClass && + InterfaceOffsetAndCount == Other.InterfaceOffsetAndCount; } uint32_t GetMemberCount() const { return MemberData >> 24; } uint32_t GetMemberStart() const { return MemberData << 8 >> 8; } + uint32_t GetInterfaceCount() const { return InterfaceOffsetAndCount >> 24; } + uint32_t GetInterfaceStart() const { + return InterfaceOffsetAndCount << 8 >> 8; + } + bool IsMultiDimensionalArray() const { return ElementsOrArrayId >> 31; } bool IsArray() const { return ElementsOrArrayId; } bool Is1DArray() const { return IsArray() && !IsMultiDimensionalArray(); } @@ -426,16 +430,20 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and DxcHLSLType(uint32_t BaseClass, uint32_t ElementsOrArrayId, D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE Type, uint8_t Rows, uint8_t Columns, uint32_t MembersCount, - uint32_t MembersStart) - : MemberData(MembersStart | (MembersCount << 24)), - Class(Class), Type(Type), Rows(Rows), Columns(Columns), - ElementsOrArrayId(ElementsOrArrayId), BaseClass(BaseClass) { + uint32_t MembersStart, uint32_t InterfaceOffset, + uint32_t InterfaceCount) + : MemberData(MembersStart | (MembersCount << 24)), Class(Class), + Type(Type), Rows(Rows), Columns(Columns), + ElementsOrArrayId(ElementsOrArrayId), BaseClass(BaseClass), + InterfaceOffsetAndCount(InterfaceOffset | (InterfaceCount << 24)) { assert(Class >= D3D_SVC_SCALAR && Class <= D3D_SVC_INTERFACE_POINTER && "Invalid class"); assert(Type >= D3D_SVT_VOID && Type <= D3D_SVT_UINT64 && "Invalid type"); assert(MembersStart < (1 << 24) && "Member start out of bounds"); + assert(InterfaceOffset < (1 << 24) && "Interface start out of bounds"); assert(MembersCount < (1 << 8) && "Member count out of bounds"); + assert(InterfaceCount < (1 << 8) && "Interface count out of bounds"); } }; @@ -504,7 +512,8 @@ struct DxcHLSLReflectionData { std::vector Arrays; std::vector ArraySizes; - std::vector MemberTypeIds; + std::vector MemberTypeIds; + std::vector TypeList; std::vector Types; std::vector Buffers; @@ -541,8 +550,8 @@ struct DxcHLSLReflectionData { Enums == Other.Enums && EnumValues == Other.EnumValues && Annotations == Other.Annotations && Arrays == Other.Arrays && ArraySizes == Other.ArraySizes && - MemberTypeIds == Other.MemberTypeIds && Types == Other.Types && - Buffers == Other.Buffers; + MemberTypeIds == Other.MemberTypeIds && TypeList == Other.TypeList && + Types == Other.Types && Buffers == Other.Buffers; } bool operator==(const DxcHLSLReflectionData &Other) const { diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 7aa8cba5c6..98402794d9 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -125,6 +125,7 @@ struct D3D12_HLSL_REFLECTION_DESC { UINT TypeCount; UINT StructCount; UINT UnionCount; + UINT InterfaceCount; }; struct D3D12_HLSL_FUNCTION_DESC { @@ -181,6 +182,8 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE, + D3D12_HLSL_NODE_TYPE_INTERFACE, + // TODO: D3D12_HLSL_NODE_TYPE_USING, // TODO: D3D12_HLSL_NODE_TYPE_PARAMETER, @@ -188,7 +191,7 @@ enum D3D12_HLSL_NODE_TYPE { 1 << 7, // Highest bit; reserved as an indicator for fwd declarations D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_INTERFACE }; struct D3D12_HLSL_NODE { @@ -271,6 +274,10 @@ DECLARE_INTERFACE(IDxcHLSLReflection) { (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + STDMETHOD(GetInterfaceTypeByIndex) + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) + PURE; + STDMETHOD(GetTypeByIndex) (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; @@ -338,6 +345,9 @@ DECLARE_INTERFACE(IDxcHLSLReflection) { STDMETHOD(GetUnionTypeByName) (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + + STDMETHOD(GetInterfaceTypeByName) + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; }; #undef INTERFACE diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 026f91b7bb..1452f17c18 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -146,7 +146,7 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, else if (RecordDecl *rec = dyn_cast(DeclSelf)) { - isFwdDeclare = !rec->isCompleteDefinition(); + isFwdDeclare = !rec->isThisDeclarationADefinition(); fwdDeclare = rec->getCanonicalDecl(); canHaveFwdDeclare = true; @@ -513,6 +513,60 @@ static uint32_t PushArray(DxcHLSLReflectionData &Refl, uint32_t ArraySizeFlat, return arrayId; } +void RegisterTypeList(DxcHLSLReflectionData &Refl, + const std::vector &TypeIds, uint32_t &Offset, + uint8_t &Len) { + + if (TypeIds.empty()) + return; + + assert(TypeIds.size() < uint8_t(-1) && + "Only allowing 256 types in a type list"); + + uint32_t i = 0; + uint32_t j = uint32_t(Refl.TypeList.size()); + uint32_t k = 0; + + Offset = 0; + + for (; i < j; ++i) { + + if (k == TypeIds.size()) + break; + + if (TypeIds[k] != Refl.TypeList[i]) { + + if (k) + i = Offset; + + k = 0; + break; + } + + if (!k) + Offset = i; + + ++k; + } + + if (k != TypeIds.size()) { + + uint32_t oldSiz = uint32_t(Refl.TypeList.size()); + + assert(oldSiz + TypeIds.size() < (1u << 24) && + "Only allowing 16Mi total interfaces"); + + Refl.TypeList.resize(oldSiz + TypeIds.size()); + + std::memcpy(Refl.TypeList.data() + oldSiz, TypeIds.data(), + TypeIds.size() * sizeof(uint32_t)); + + Offset = oldSiz; + } + + Len = uint8_t(TypeIds.size()); +} + uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, QualType Original, bool DefaultRowMaj) { @@ -559,12 +613,22 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, //And base type D3D_SHADER_VARIABLE_CLASS cls = D3D_SVC_STRUCT; + + if (const RecordType *RT = underlying->getAs()) { + + const RecordDecl *RD = RT->getDecl(); + + if (RD->getTagKind() == TTK_Interface) + cls = D3D_SVC_INTERFACE_CLASS; + } + uint8_t rows = 0, columns = 0; uint32_t membersCount = 0; uint32_t membersOffset = 0; uint32_t baseType = uint32_t(-1); + std::vector interfaces; if (const RecordType *record = underlying->getAs()) { @@ -684,9 +748,11 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, CXXRecordDecl *BaseDecl = cast(qualType->castAs()->getDecl()); - // TODO: Interfaces? - if (BaseDecl->isInterface()) + if (BaseDecl->isInterface()) { + interfaces.push_back( + GenerateTypeInfo(ASTCtx, Refl, qualType, DefaultRowMaj)); continue; + } assert(baseType == uint32_t(-1) && "Multiple base types isn't supported in HLSL"); @@ -707,7 +773,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, continue; if (!membersCount) - membersOffset = (uint32_t)Refl.MemberTypeIds.size(); + membersOffset = uint32_t(Refl.MemberTypeIds.size()); std::string name = fieldDecl->getName(); @@ -834,10 +900,17 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, assert(Refl.Types.size() < uint32_t(-1) && "Type id out of bounds"); - DxcHLSLType hlslType(baseType, elementsOrArrayId, cls, type, rows, - columns, membersCount, membersOffset); + assert(interfaces.size() < uint8_t(-1) && "Only allowing 256 interfaces"); + + uint32_t interfaceOffset = 0; + uint8_t interfaceCount = 0; + RegisterTypeList(Refl, interfaces, interfaceOffset, interfaceCount); - uint32_t i = 0, j = uint32_t(Refl.Types.size()); + DxcHLSLType hlslType(baseType, elementsOrArrayId, cls, type, rows, columns, + membersCount, membersOffset, interfaceOffset, interfaceCount); + + uint32_t i = 0; + uint32_t j = uint32_t(Refl.Types.size()); for (; i < j; ++i) if (Refl.Types[i] == hlslType && (!hasSymbols || Refl.TypeNameIds[i] == nameId)) @@ -1319,40 +1392,42 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) continue; - bool isCompleteDefinition = RecDecl->isCompleteDefinition(); + bool isDefinition = RecDecl->isThisDeclarationADefinition(); - bool pushObj = false; - bool isStruct = RecDecl->getTagKind() == TTK_Struct; + D3D12_HLSL_NODE_TYPE type = D3D12_HLSL_NODE_TYPE_RESERVED; switch (RecDecl->getTagKind()) { case TTK_Struct: + type = D3D12_HLSL_NODE_TYPE_STRUCT; + break; + case TTK_Union: - pushObj = true; + type = D3D12_HLSL_NODE_TYPE_UNION; break; - // TODO: case TTK_Interface: Is this HLSL's interface or something else? - // break; + case TTK_Interface: + type = D3D12_HLSL_NODE_TYPE_INTERFACE; + break; } - if (pushObj) { + if (type != D3D12_HLSL_NODE_TYPE_RESERVED) { uint32_t typeId = 0; - if (isCompleteDefinition) + if (isDefinition) typeId = GenerateTypeInfo( ASTCtx, Refl, RecDecl->getASTContext().getRecordType(RecDecl), DefaultRowMaj); uint32_t self = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), RecDecl->getName(), RecDecl, - isStruct ? D3D12_HLSL_NODE_TYPE_STRUCT : D3D12_HLSL_NODE_TYPE_UNION, + Refl, SM, ASTCtx.getLangOpts(), RecDecl->getName(), RecDecl, type, ParentNodeId, typeId, nullptr, &FwdDecls); if (self == uint32_t(-1)) // Duplicate fwd definition continue; - if (isCompleteDefinition) + if (isDefinition) RecursiveReflectHLSL(*RecDecl, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, self, DefaultRowMaj, FwdDecls); @@ -1430,9 +1505,10 @@ static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { - static const char *arr[] = { - "Register", "Function", "Enum", "EnumValue", "Namespace", - "Variable", "Typedef", "Struct", "Union", "StaticVariable"}; + static const char *arr[] = {"Register", "Function", "Enum", + "EnumValue", "Namespace", "Variable", + "Typedef", "Struct", "Union", + "StaticVariable", "Interface"}; return arr[uint32_t(type)]; } @@ -1442,7 +1518,7 @@ static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, std::string type; - if (Type.Class != D3D_SVC_STRUCT) { + if (Type.Class != D3D_SVC_STRUCT && Type.Class != D3D_SVC_INTERFACE_CLASS) { static const char *arr[] = {"void", "bool", @@ -1580,7 +1656,15 @@ static void RecursePrintType(const DxcHLSLReflectionData &Refl, uint32_t TypeId, PrintTypeInfo(Refl, type, name).c_str()); if (type.BaseClass != uint32_t(-1)) - RecursePrintType(Refl, type.BaseClass, Depth + 1, Prefix); + RecursePrintType(Refl, type.BaseClass, Depth + 1, + (std::string("BaseClass ") + Prefix).c_str()); + + for (uint32_t i = 0; i < type.GetInterfaceCount(); ++i) { + + uint32_t interfaceId = type.GetInterfaceStart() + i; + + RecursePrintType(Refl, Refl.TypeList[interfaceId], Depth + 1, "Interface "); + } for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { @@ -1648,7 +1732,25 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, } case D3D12_HLSL_NODE_TYPE_UNION: - case D3D12_HLSL_NODE_TYPE_STRUCT: // Children are Variables + case D3D12_HLSL_NODE_TYPE_STRUCT: { // Children are Variables + + const DxcHLSLType &type = Refl.Types[localId]; + + if (type.BaseClass != uint32_t(-1)) + RecursePrintType(Refl, type.BaseClass, Depth, "BaseClass "); + + for (uint32_t i = 0; i < type.GetInterfaceCount(); ++i) { + + uint32_t interfaceId = type.GetInterfaceStart() + i; + + RecursePrintType(Refl, Refl.TypeList[interfaceId], Depth, + "Interface "); + } + + break; + } + + case D3D12_HLSL_NODE_TYPE_INTERFACE: break; // TODO: case D3D12_HLSL_NODE_TYPE_USING: @@ -1693,7 +1795,7 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1, j); - if (node.IsFwdDeclare()) + if (node.IsFwdDeclare() && node.IsFwdBckDefined()) RecursePrint(Refl, node.GetFwdBck(), Depth, IndexInParent, true); return node.GetChildCount(); @@ -1725,6 +1827,9 @@ struct DxcHLSLHeader { uint32_t Types; uint32_t Buffers; + + uint32_t TypeListCount; + uint32_t Padding; }; template @@ -1922,7 +2027,7 @@ uint32_t RecurseNameGeneration(DxcHLSLReflectionData &Refl, uint32_t NodeId, DxcHLSLNode node = Refl.Nodes[NodeId]; - if (node.IsFwdDeclare()) { + if (node.IsFwdDeclare() && node.IsFwdBckDefined()) { NodeId = node.GetFwdBck(); node = Refl.Nodes[NodeId]; } @@ -1982,7 +2087,7 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, - Arrays, MemberTypeIds, MemberNameIds, Types, TypeNameIds, Buffers); + Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, TypeNameIds, Buffers); Bytes.resize(toReserve); @@ -1997,14 +2102,14 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { uint32_t(EnumValues.size()), uint32_t(Annotations.size()), uint32_t(Arrays.size()), uint32_t(ArraySizes.size()), uint32_t(MemberTypeIds.size()), uint32_t(Types.size()), - uint32_t(Buffers.size())}; + uint32_t(Buffers.size()), uint32_t(TypeList.size())}; toReserve += sizeof(DxcHLSLHeader); Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, - ArraySizes, Arrays, MemberTypeIds, MemberNameIds, Types, TypeNameIds, - Buffers); + ArraySizes, Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, + TypeNameIds, Buffers); } DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes, @@ -2036,9 +2141,9 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes NodeSymbols, nodeSymbolCount, Registers, header.Registers, Functions, header.Functions, Enums, header.Enums, EnumValues, header.EnumValues, Annotations, header.Annotations, ArraySizes, header.ArraySizes, - Arrays, header.Arrays, MemberTypeIds, header.Members, MemberNameIds, - memberSymbolCount, Types, header.Types, TypeNameIds, typeSymbolCount, - Buffers, header.Buffers); + Arrays, header.Arrays, MemberTypeIds, header.Members, TypeList, + header.TypeListCount, MemberNameIds, memberSymbolCount, Types, + header.Types, TypeNameIds, typeSymbolCount, Buffers, header.Buffers); // Validation errors are throws to prevent accessing invalid data @@ -2098,11 +2203,20 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_STRUCT: case D3D12_HLSL_NODE_TYPE_UNION: + case D3D12_HLSL_NODE_TYPE_INTERFACE: allowFwdDeclare = true; maxValue = node.IsFwdDeclare() ? 1 : header.Types; break; } + if ((node.GetNodeType() == D3D12_HLSL_NODE_TYPE_REGISTER || + node.GetNodeType() == D3D12_HLSL_NODE_TYPE_VARIABLE) && + Nodes[node.GetParentId()].GetNodeType() == + D3D12_HLSL_NODE_TYPE_INTERFACE) + throw std::invalid_argument( + "Node " + std::to_string(i) + + " is interface but has registers or variables"); + if (node.IsFwdDeclare() && !allowFwdDeclare) throw std::invalid_argument("Node " + std::to_string(i) + " is fwd declare but that's not permitted"); @@ -2253,6 +2367,11 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes throw std::invalid_argument("Member " + std::to_string(i) + " points to an invalid string"); } + + for (uint32_t i = 0; i < header.TypeListCount; ++i) + if (TypeList[i] >= header.Types) + throw std::invalid_argument("Type list index " + std::to_string(i) + + " points to an invalid type"); for (uint32_t i = 0; i < header.Types; ++i) { @@ -2264,6 +2383,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if ((type.BaseClass != uint32_t(-1) && type.BaseClass >= header.Types) || type.GetMemberStart() + type.GetMemberCount() > header.Members || + type.GetInterfaceStart() + type.GetInterfaceCount() > header.TypeListCount || (type.ElementsOrArrayId >> 31 && (type.ElementsOrArrayId << 1 >> 1) >= header.Arrays)) throw std::invalid_argument( @@ -2329,6 +2449,11 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (!type.GetMemberCount()) throw std::invalid_argument("Type (struct) " + std::to_string(i) + " is missing children"); + + [[fallthrough]]; + + case D3D_SVC_INTERFACE_CLASS: + if (type.Type) throw std::invalid_argument("Type (struct) " + std::to_string(i) + diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 5c3bb6a192..0961566422 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -157,6 +157,7 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { std::unordered_map m_NameToMemberId; std::vector m_MemberTypes; CHLSLReflectionType *m_pBaseClass; + std::vector m_Interfaces; const DxcHLSLReflectionData *m_Data; uint32_t m_TypeId; @@ -232,13 +233,13 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { m_NameToMemberId.clear(); for (uint32_t i = 0; i < memberCount; ++i) { - + uint32_t memberId = type.GetMemberStart() + i; m_MemberTypes[i] = &Types[Data.MemberTypeIds[memberId]]; if (hasNames) { - + const std::string &name = Data.Strings[Data.MemberNameIds[memberId]]; m_MemberNames[i] = name; @@ -249,6 +250,13 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { if (type.BaseClass != uint32_t(-1)) m_pBaseClass = &Types[type.BaseClass]; + uint32_t interfaceCount = type.GetInterfaceCount(); + + m_Interfaces.resize(interfaceCount); + + for (uint32_t i = 0; i < interfaceCount; ++i) + m_Interfaces[i] = &Types[Data.TypeList[type.GetInterfaceStart() + i]]; + return S_OK; } @@ -312,19 +320,25 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { } STDMETHOD_(UINT, GetNumInterfaces)() override { - // HLSL interfaces have been deprecated - return 0; + return uint32_t(m_Interfaces.size()); } STDMETHOD(ImplementsInterface)(ID3D12ShaderReflectionType *pBase) override { - // HLSL interfaces have been deprecated + + for (CHLSLReflectionType *interf : m_Interfaces) + if (pBase == interf) + return S_OK; + return S_FALSE; } STDMETHOD_(ID3D12ShaderReflectionType *, GetInterfaceByIndex) (UINT uIndex) override { - // HLSL interfaces have been deprecated - return nullptr; + + if (uIndex >= m_Interfaces.size()) + return nullptr; + + return m_Interfaces[uIndex]; } }; @@ -549,6 +563,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { UNION, ENUM, FUNCTION, + INTERFACE, COUNT }; @@ -577,7 +592,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { !node.GetParentId()) globalVars.push_back(i); - // Filter out fwd declarations for structs, unions, functions, enums + // Filter out fwd declarations for structs, unions, interfaces, functions, enums if (!node.IsFwdDeclare()) { @@ -593,6 +608,10 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { type = FwdDeclType::UNION; break; + case D3D12_HLSL_NODE_TYPE_INTERFACE: + type = FwdDeclType::INTERFACE; + break; + case D3D12_HLSL_NODE_TYPE_FUNCTION: type = FwdDeclType::FUNCTION; break; @@ -692,7 +711,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { uint32_t(Data.Nodes.size()), uint32_t(Data.Types.size()), uint32_t(NonFwdIds[int(FwdDeclType::STRUCT)].size()), - uint32_t(NonFwdIds[int(FwdDeclType::UNION)].size())}; + uint32_t(NonFwdIds[int(FwdDeclType::UNION)].size()), + uint32_t(NonFwdIds[int(FwdDeclType::INTERFACE)].size())}; return S_OK; } @@ -974,6 +994,19 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { *ppType = &Types[NonFwdIds[int(FwdDeclType::UNION)][Index]]; return S_OK; } + + STDMETHOD(GetInterfaceTypeByIndex) + (THIS_ _In_ UINT Index, + _Outptr_ ID3D12ShaderReflectionType **ppType) override { + + IFR(ZeroMemoryToOut(ppType)); + + if (Index >= NonFwdIds[int(FwdDeclType::INTERFACE)].size()) + return E_INVALIDARG; + + *ppType = &Types[NonFwdIds[int(FwdDeclType::INTERFACE)][Index]]; + return S_OK; + } STDMETHOD(GetNodeSymbolDesc) (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE_SYMBOL *pDesc) override { @@ -1179,6 +1212,27 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { *ppType = &Types[it->second]; return S_OK; } + + STDMETHOD(GetInterfaceTypeByName) + (THIS_ _In_ LPCSTR Name, + _Outptr_ ID3D12ShaderReflectionType **ppType) override { + + IFR(ZeroMemoryToOut(ppType)); + + if (!Name) + return E_POINTER; + + if (!(Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO)) + return E_INVALIDARG; + + auto it = NameToNonFwdIds[int(FwdDeclType::INTERFACE)].find(Name); + + if (it == NameToNonFwdIds[int(FwdDeclType::INTERFACE)].end()) + return E_INVALIDARG; + + *ppType = &Types[it->second]; + return S_OK; + } }; namespace { From f6cce18e4c6805235078d6d97d6974ac1c1004b9 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 27 Sep 2025 15:25:33 +0200 Subject: [PATCH 047/126] Implemented IsEqual and IsOfType in CHLSLReflectionType --- tools/clang/tools/libclang/dxcreflector.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 0961566422..98a96b5187 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -167,12 +167,17 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { public: STDMETHOD(IsEqual)(ID3D12ShaderReflectionType *pType) override { - // TODO: implement this check, if users actually depend on it - return S_FALSE; + return (this == pType) ? S_OK : S_FALSE; } STDMETHOD(IsOfType)(ID3D12ShaderReflectionType *pType) override { - // TODO: implement `class`-related features, if requested + + if (this == pType) + return S_OK; + + if (m_pBaseClass) + return m_pBaseClass->IsOfType(pType); + return S_FALSE; } From 450fec336f2de237032ea64808d047274a351f60 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 27 Sep 2025 16:29:03 +0200 Subject: [PATCH 048/126] Added support for variables of builtin object types such as (RW)Texture(1D/2D/3D/Cube)(Array), SamplerState, (RW)ByteAddressBuffer, (RW/Append/Consume)StructuredBuffer, (RW)Buffer. TODO: Add body of buffer/texture and unsupported types from D3D_SVC_OBJECT such as RTAS. --- .../tools/dxcreflection/DxcReflection.cpp | 107 +++++++++--------- 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 1452f17c18..77c3ca7014 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -630,33 +630,59 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, uint32_t baseType = uint32_t(-1); std::vector interfaces; + D3D_SHADER_VARIABLE_TYPE type = D3D_SVT_VOID; + if (const RecordType *record = underlying->getAs()) { bool standardType = false; RecordDecl *recordDecl = record->getDecl(); + static const std::unordered_map + lookup = std::unordered_map{{ + {"vector", D3D_SHADER_VARIABLE_TYPE(-1)}, + {"matrix", D3D_SHADER_VARIABLE_TYPE(-2)}, + {"Texture1D", D3D_SVT_TEXTURE1D}, + {"Texture2D", D3D_SVT_TEXTURE2D}, + {"RWTexture1D", D3D_SVT_RWTEXTURE1D}, + {"RWTexture2D", D3D_SVT_RWTEXTURE2D}, + {"Texture2DMS", D3D_SVT_TEXTURE2DMS}, + {"Texture3D", D3D_SVT_TEXTURE3D}, + {"RWTexture3D", D3D_SVT_RWTEXTURE3D}, + {"TextureCube", D3D_SVT_TEXTURECUBE}, + {"Texture1DArray", D3D_SVT_TEXTURE1DARRAY}, + {"Texture2DArray", D3D_SVT_TEXTURE2DARRAY}, + {"RWTexture1DArray", D3D_SVT_RWTEXTURE1DARRAY}, + {"RWTexture2DArray", D3D_SVT_RWTEXTURE2DARRAY}, + {"Texture2DMSArray", D3D_SVT_TEXTURE2DMSARRAY}, + {"TextureCubeArray", D3D_SVT_TEXTURECUBEARRAY}, + {"SamplerState", D3D_SVT_SAMPLER}, + {"ByteAddressBuffer", D3D_SVT_BYTEADDRESS_BUFFER}, + {"RWByteAddressBuffer", D3D_SVT_RWBYTEADDRESS_BUFFER}, + {"StructuredBuffer", D3D_SVT_STRUCTURED_BUFFER}, + {"RWStructuredBuffer", D3D_SVT_RWSTRUCTURED_BUFFER}, + {"AppendStructuredBuffer", D3D_SVT_APPEND_STRUCTURED_BUFFER}, + {"ConsumeStructuredBuffer", D3D_SVT_CONSUME_STRUCTURED_BUFFER}, + {"RWBuffer", D3D_SVT_RWBUFFER}, + {"Buffer", D3D_SVT_BUFFER}, + {"ConstantBuffer", D3D_SVT_CBUFFER} + }}; + if (const ClassTemplateSpecializationDecl *templateClass = dyn_cast(recordDecl)) { - const std::string &name = templateClass->getIdentifier()->getName(); + std::string name = templateClass->getIdentifier()->getName(); const ArrayRef ¶ms = templateClass->getTemplateArgs().asArray(); - uint32_t magic = 0; - std::memcpy(&magic, name.c_str(), std::min(sizeof(magic), name.size())); - - std::string_view subs = - name.size() < sizeof(magic) - ? std::string_view() - : std::string_view(name).substr(sizeof(magic)); - - switch (magic) { + auto it = lookup.find(name); - case DXC_FOURCC('v', 'e', 'c', 't'): + if (it != lookup.end()) { + + D3D_SHADER_VARIABLE_TYPE svt = it->second; - if (subs == "or") { + if (svt == -1) { //Reserved as 'vector' rows = 1; @@ -671,11 +697,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, standardType = true; } - break; - - case DXC_FOURCC('m', 'a', 't', 'r'): - - if (subs == "ix") { + else if (svt == -2) { //Reserved as 'matrix' assert(params.size() == 3 && params[0].getKind() == TemplateArgument::Type && @@ -698,45 +720,28 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, standardType = true; } - break; + else { + type = svt; + cls = D3D_SVC_OBJECT; + } } + } - // TODO: - // D3D_SVT_TEXTURE = 5, - // D3D_SVT_TEXTURE1D = 6, - // D3D_SVT_TEXTURE2D = 7, - // D3D_SVT_TEXTURE3D = 8, - // D3D_SVT_TEXTURECUBE = 9, - // D3D_SVT_SAMPLER = 10, - // D3D_SVT_SAMPLER1D = 11, - // D3D_SVT_SAMPLER2D = 12, - // D3D_SVT_SAMPLER3D = 13, - // D3D_SVT_SAMPLERCUBE = 14, - // D3D_SVT_BUFFER = 25, - // D3D_SVT_CBUFFER = 26, - // D3D_SVT_TBUFFER = 27, - // D3D_SVT_TEXTURE1DARRAY = 28, - // D3D_SVT_TEXTURE2DARRAY = 29, - // D3D_SVT_TEXTURE2DMS = 32, - // D3D_SVT_TEXTURE2DMSARRAY = 33, - // D3D_SVT_TEXTURECUBEARRAY = 34, - // D3D_SVT_RWTEXTURE1D = 40, - // D3D_SVT_RWTEXTURE1DARRAY = 41, - // D3D_SVT_RWTEXTURE2D = 42, - // D3D_SVT_RWTEXTURE2DARRAY = 43, - // D3D_SVT_RWTEXTURE3D = 44, - // D3D_SVT_RWBUFFER = 45, - // D3D_SVT_BYTEADDRESS_BUFFER = 46, - // D3D_SVT_RWBYTEADDRESS_BUFFER = 47, - // D3D_SVT_STRUCTURED_BUFFER = 48, - // D3D_SVT_RWSTRUCTURED_BUFFER = 49, - // D3D_SVT_APPEND_STRUCTURED_BUFFER = 50, - // D3D_SVT_CONSUME_STRUCTURED_BUFFER = 51, + else { + + std::string name = recordDecl->getName(); + + auto it = lookup.find(name); + + if (it != lookup.end()) { + type = it->second; + cls = D3D_SVC_OBJECT; + } } // Fill members - if (!standardType && recordDecl->isCompleteDefinition()) { + if (!standardType && recordDecl->isCompleteDefinition() && cls != D3D_SVC_OBJECT) { // Base types @@ -813,8 +818,6 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, //Type name - D3D_SHADER_VARIABLE_TYPE type = D3D_SVT_VOID; - if (const BuiltinType *bt = dyn_cast(underlying)) { if (!rows) From 04da70e046448d49979fdf7b5a4b0fe96a57bca3 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 27 Sep 2025 18:15:34 +0200 Subject: [PATCH 049/126] Replaced asserts that have to deal with bit limits with std::invalid_argument to avoid crashes in release mode. Only made asserts optional that are about compiler-related things that the user doesn't control but are a logic issue by me. Also made the -> DxcHLSLReflectionData into an Initialize since it can throw and in that case it just returns false. --- include/dxc/DxcReflection/DxcReflection.h | 112 ++++++++----- .../tools/dxcreflection/DxcReflection.cpp | 147 +++++++++++------- tools/clang/tools/libclang/dxcreflector.cpp | 15 +- 3 files changed, 175 insertions(+), 99 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index b86ad8019c..26506694bd 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -70,20 +70,26 @@ class DxcHLSLNode { ChildCountFwdBckLo(ChildCount | (0xFFu << 24)), FwdBckHi(0xFFFF), AnnotationStart(AnnotationStart), SemanticId(SemanticId), Padding(0) { - assert(NodeType >= D3D12_HLSL_NODE_TYPE_START && - NodeType <= D3D12_HLSL_NODE_TYPE_END && "Invalid enum value"); + if (NodeType < D3D12_HLSL_NODE_TYPE_START || + NodeType > D3D12_HLSL_NODE_TYPE_END) + throw std::invalid_argument("Invalid NodeType"); - assert(LocalId < ((1 << 24) - 1) && "LocalId out of bounds"); - assert(ParentId < ((1 << 24) - 1) && "ParentId out of bounds"); - assert(ChildCount < ((1 << 24) - 1) && "ChildCount out of bounds"); + if (LocalId >= ((1u << 24) - 1)) + throw std::invalid_argument("LocalId out of bounds"); + + if (ParentId >= ((1u << 24) - 1)) + throw std::invalid_argument("ParentId out of bounds"); + + if (ChildCount >= ((1u << 24) - 1)) + throw std::invalid_argument("ChildCount out of bounds"); if (IsFwdDeclare) { - assert(!AnnotationCount && - "Fwd declares aren't allowed to have annotations"); + if (AnnotationCount) + throw std::invalid_argument("Fwd declares aren't allowed to have annotations"); - assert(!ChildCount && - "Fwd declares aren't allowed to have children"); + if (ChildCount) + throw std::invalid_argument("Fwd declares aren't allowed to have children"); Type |= 0x80; } @@ -118,8 +124,12 @@ class DxcHLSLNode { void ResolveFwdDeclare(uint32_t SelfId, DxcHLSLNode &Definition, uint32_t DefinitionId) { - assert(SelfId < ((1 << 24) - 1) && "SelfId out of bounds"); - assert(DefinitionId < ((1 << 24) - 1) && "DefinitionId out of bounds"); + if (SelfId >= ((1u << 24) - 1)) + throw std::invalid_argument("SelfId out of bounds"); + + if (DefinitionId >= ((1u << 24) - 1)) + throw std::invalid_argument("DefinitionId out of bounds"); + assert(DefinitionId != SelfId && "NodeId can't be definition id!"); assert(IsFwdDeclare() && "Can't run ResolveFwdDeclare on a node that's no fwd decl"); @@ -153,7 +163,10 @@ class DxcHLSLNode { } void IncreaseChildCount() { - assert(GetChildCount() < ((1 << 24) - 1) && "Child count out of bounds"); + + if (GetChildCount() >= ((1u << 24) - 1)) + throw std::invalid_argument("Child count out of bounds"); + ++ChildCountFwdBckLo; } @@ -201,11 +214,14 @@ struct DxcHLSLNodeSymbol { (SourceColumnEnd >> 16 << 6) | (SourceLineStart << 12)) { - assert(SourceColumnStart < (1 << 22) && "SourceColumnStart out of bounds"); - assert(SourceColumnEnd < (1 << 22) && "SourceColumnEnd out of bounds"); + if (SourceColumnStart >= (1u << 22)) + throw std::invalid_argument("SourceColumnStart out of bounds"); + + if (SourceColumnEnd >= (1u << 22)) + throw std::invalid_argument("SourceColumnEnd out of bounds"); - assert(SourceLineStart < ((1 << 20) - 1) && - "SourceLineStart out of bounds"); + if (SourceLineStart >= ((1u << 20) - 1)) + throw std::invalid_argument("SourceLineStart out of bounds"); } uint32_t GetSourceLineStart() const { @@ -279,7 +295,8 @@ struct DxcHLSLFunction { (HasReturn ? (1 << 30) : 0) | (HasDefinition ? (1 << 31) : 0)) { - assert(NumParameters < (1 << 30) && "NumParameters out of bounds"); + if (NumParameters >= (1u << 30)) + throw std::invalid_argument("NumParameters out of bounds"); } uint32_t GetNumParameters() const { @@ -337,16 +354,19 @@ struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus ReturnType(ReturnType), Dimension(Dimension), NodeId(NodeId), ArrayId(ArrayId), BufferId(BufferId) { - assert(Type >= D3D_SIT_CBUFFER && Type <= D3D_SIT_UAV_FEEDBACKTEXTURE && - "Invalid type"); + if (Type < D3D_SIT_CBUFFER || Type > D3D_SIT_UAV_FEEDBACKTEXTURE) + throw std::invalid_argument("Invalid type"); - assert(ReturnType >= 0 && ReturnType <= D3D_RETURN_TYPE_CONTINUED && - "Invalid return type"); + if (ReturnType < 0 || + ReturnType > D3D_RETURN_TYPE_CONTINUED) + throw std::invalid_argument("Invalid return type"); - assert(Dimension >= D3D_SRV_DIMENSION_UNKNOWN && - Dimension <= D3D_SRV_DIMENSION_BUFFEREX && "Invalid srv dimension"); + if (Dimension < D3D_SRV_DIMENSION_UNKNOWN || + Dimension > D3D_SRV_DIMENSION_BUFFEREX) + throw std::invalid_argument("Invalid srv dimension"); - assert(!(uFlags >> 8) && "Invalid user flags"); + if (uFlags >> 8) + throw std::invalid_argument("Invalid user flags"); } bool operator==(const DxcHLSLRegister &other) const { @@ -364,8 +384,11 @@ struct DxcHLSLArray { DxcHLSLArray(uint32_t ArrayElem, uint32_t ArrayStart) : ArrayElemStart((ArrayElem << 26) | ArrayStart) { - assert(ArrayElem <= 32 && ArrayElem > 1 && "ArrayElem out of bounds"); - assert(ArrayStart < (1 << 26) && "ArrayStart out of bounds"); + if (ArrayElem <= 1 || ArrayElem > 32) + throw std::invalid_argument("ArrayElem out of bounds"); + + if (ArrayStart >= (1u << 26)) + throw std::invalid_argument("ArrayStart out of bounds"); } bool operator==(const DxcHLSLArray &Other) const { @@ -437,13 +460,23 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and ElementsOrArrayId(ElementsOrArrayId), BaseClass(BaseClass), InterfaceOffsetAndCount(InterfaceOffset | (InterfaceCount << 24)) { - assert(Class >= D3D_SVC_SCALAR && Class <= D3D_SVC_INTERFACE_POINTER && - "Invalid class"); - assert(Type >= D3D_SVT_VOID && Type <= D3D_SVT_UINT64 && "Invalid type"); - assert(MembersStart < (1 << 24) && "Member start out of bounds"); - assert(InterfaceOffset < (1 << 24) && "Interface start out of bounds"); - assert(MembersCount < (1 << 8) && "Member count out of bounds"); - assert(InterfaceCount < (1 << 8) && "Interface count out of bounds"); + if (Class < D3D_SVC_SCALAR || Class > D3D_SVC_INTERFACE_POINTER) + throw std::invalid_argument("Invalid class"); + + if (Type < D3D_SVT_VOID || Type > D3D_SVT_UINT64) + throw std::invalid_argument("Invalid type"); + + if (MembersStart >= (1u << 24)) + throw std::invalid_argument("Member start out of bounds"); + + if (InterfaceOffset >= (1u << 24)) + throw std::invalid_argument("Interface start out of bounds"); + + if (MembersCount >= (1u << 8)) + throw std::invalid_argument("Member count out of bounds"); + + if (InterfaceCount >= (1u << 8)) + throw std::invalid_argument("Interface count out of bounds"); } }; @@ -467,7 +500,9 @@ struct DxcHLSLAnnotation { DxcHLSLAnnotation(uint32_t StringNonDebug, bool IsBuiltin) : StringNonDebugAndIsBuiltin(StringNonDebug | (IsBuiltin ? (1u << 31) : 0)) { - assert(StringNonDebug < (1u << 31) && "String non debug out of bounds"); + + if (StringNonDebug >= (1u << 31)) + throw std::invalid_argument("String non debug out of bounds"); } bool operator==(const DxcHLSLAnnotation &other) const { @@ -539,10 +574,11 @@ struct DxcHLSLReflectionData { DxcHLSLReflectionData(const std::vector &Bytes, bool MakeNameLookupTable); - DxcHLSLReflectionData(clang::CompilerInstance &Compiler, - clang::TranslationUnitDecl &Ctx, - uint32_t AutoBindingSpace, - D3D12_HLSL_REFLECTION_FEATURE Features, bool DefaultRowMaj); + static bool Initialize(clang::CompilerInstance &Compiler, + clang::TranslationUnitDecl &Ctx, + uint32_t AutoBindingSpace, + D3D12_HLSL_REFLECTION_FEATURE Features, + bool DefaultRowMaj, DxcHLSLReflectionData &Result); bool IsSameNonDebug(const DxcHLSLReflectionData &Other) const { return StringsNonDebug == Other.StringsNonDebug && Nodes == Other.Nodes && diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 77c3ca7014..8424971817 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -33,11 +33,13 @@ struct DxcRegisterTypeInfo { static uint32_t RegisterString(DxcHLSLReflectionData &Refl, const std::string &Name, bool isNonDebug) { - assert(Name.size() < 32768 && "Strings are limited to 32767"); + if (Name.size() >= 32768) + throw std::invalid_argument("Strings are limited to 32767"); if (isNonDebug) { - assert(Refl.StringsNonDebug.size() < uint32_t(-1) && "Strings overflow"); + if (Refl.StringsNonDebug.size() >= uint32_t(-1)) + throw std::invalid_argument("Strings overflow"); auto it = Refl.StringsToIdNonDebug.find(Name); @@ -51,7 +53,8 @@ static uint32_t RegisterString(DxcHLSLReflectionData &Refl, return stringId; } - assert(Refl.Strings.size() < uint32_t(-1) && "Strings overflow"); + if (Refl.Strings.size() >= uint32_t(-1)) + throw std::invalid_argument("Strings overflow"); auto it = Refl.StringsToId.find(Name); @@ -72,8 +75,11 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, uint32_t LocalId, const SourceRange *Range = nullptr, std::unordered_map *FwdDecls = nullptr) { - assert(Refl.Nodes.size() < (1 << 24) && "Nodes overflow"); - assert(LocalId < (1 << 24) && "LocalId overflow"); + if (Refl.Nodes.size() >= (1u << 24)) + throw std::invalid_argument("Nodes overflow"); + + if (LocalId >= (1u << 24)) + throw std::invalid_argument("LocalId overflow"); uint32_t nodeId = Refl.Nodes.size(); @@ -86,28 +92,32 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, for (const Attr *attr : DeclSelf->attrs()) { if (const AnnotateAttr *annotate = dyn_cast(attr)) { - assert(Refl.Annotations.size() < (1 << 16) && "Out of annotations"); + if (Refl.Annotations.size() >= (1u << 16)) + throw std::invalid_argument("Out of annotations"); Refl.Annotations.push_back(DxcHLSLAnnotation( RegisterString(Refl, annotate->getAnnotation().str(), true), false)); - assert(annotationCount != uint8_t(-1) && - "Annotation count out of bounds"); + if (annotationCount >= uint8_t(-1)) + throw std::invalid_argument("Annotation count out of bounds"); + ++annotationCount; } else if (const HLSLShaderAttr *shaderAttr = dyn_cast(attr)) { - assert(Refl.Annotations.size() < (1 << 16) && "Out of annotations"); + if (Refl.Annotations.size() >= (1u << 16)) + throw std::invalid_argument("Out of annotations"); Refl.Annotations.push_back(DxcHLSLAnnotation( RegisterString( Refl, "shader(\"" + shaderAttr->getStage().str() + "\")", true), true)); - assert(annotationCount != uint8_t(-1) && - "Annotation count out of bounds"); + if (annotationCount >= uint8_t(-1)) + throw std::invalid_argument("Annotation count out of bounds"); + ++annotationCount; } @@ -206,8 +216,8 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, std::string fileName = presumed.getFilename(); - assert(fileName == presumedEnd.getFilename() && - "End and start are not in the same file"); + if (fileName != presumedEnd.getFilename()) + throw std::invalid_argument("End and start are not in the same file"); auto it = Refl.StringToSourceId.find(fileName); uint32_t i; @@ -222,12 +232,20 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, i = it->second; } - assert(i < 65535 && "Source file count is limited to 16-bit"); - assert((endLine - startLine) < 65535 && - "Source line count is limited to 16-bit"); - assert(startLine < 1048576 && "Source line start is limited to 20-bit"); - assert(startCol < (1 << 22) && "Column start is limited to 22-bit"); - assert(endCol < (1 << 22) && "Column end is limited to 22-bit"); + if (i >= 65535) + throw std::invalid_argument("Source file count is limited to 16-bit"); + + if ((endLine - startLine) >= 65535) + throw std::invalid_argument("Source line count is limited to 16-bit"); + + if (startLine >= 1048576) + throw std::invalid_argument("Source line start is limited to 20-bit"); + + if (startCol >= (1u << 22)) + throw std::invalid_argument("Column start is limited to 22-bit"); + + if (endCol >= (1u << 22)) + throw std::invalid_argument("Column end is limited to 22-bit"); sourceLineCount = uint16_t(endLine - startLine + 1); sourceLineStart = startLine; @@ -483,13 +501,16 @@ static uint32_t PushArray(DxcHLSLReflectionData &Refl, uint32_t ArraySizeFlat, if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) return uint32_t(-1); - assert(Refl.Arrays.size() < uint32_t((1u << 31) - 1) && "Arrays would overflow"); + if (Refl.Arrays.size() >= uint32_t((1u << 31) - 1)) + throw std::invalid_argument("Arrays would overflow"); + uint32_t arrayId = uint32_t(Refl.Arrays.size()); uint32_t arrayCountStart = uint32_t(Refl.ArraySizes.size()); uint32_t numArrayElements = std::min(size_t(32), ArraySize.size()); - assert(Refl.ArraySizes.size() + numArrayElements < ((1 << 26) - 1) && - "Array elements would overflow"); + + if (Refl.ArraySizes.size() + numArrayElements >= ((1u << 26) - 1)) + throw std::invalid_argument("Array elements would overflow"); for (uint32_t i = 0; i < ArraySize.size() && i < 8; ++i) { @@ -513,15 +534,15 @@ static uint32_t PushArray(DxcHLSLReflectionData &Refl, uint32_t ArraySizeFlat, return arrayId; } -void RegisterTypeList(DxcHLSLReflectionData &Refl, +static void RegisterTypeList(DxcHLSLReflectionData &Refl, const std::vector &TypeIds, uint32_t &Offset, uint8_t &Len) { if (TypeIds.empty()) return; - assert(TypeIds.size() < uint8_t(-1) && - "Only allowing 256 types in a type list"); + if (TypeIds.size() >= uint8_t(-1)) + throw std::invalid_argument("Only allowing 256 types in a type list"); uint32_t i = 0; uint32_t j = uint32_t(Refl.TypeList.size()); @@ -553,8 +574,8 @@ void RegisterTypeList(DxcHLSLReflectionData &Refl, uint32_t oldSiz = uint32_t(Refl.TypeList.size()); - assert(oldSiz + TypeIds.size() < (1u << 24) && - "Only allowing 16Mi total interfaces"); + if (oldSiz + TypeIds.size() >= (1u << 24)) + throw std::invalid_argument("Only allowing 16Mi total interfaces"); Refl.TypeList.resize(oldSiz + TypeIds.size()); @@ -791,9 +812,14 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, ++membersCount; } - if (membersCount) + if (membersCount) { + Refl.MemberTypeIds.resize(Refl.MemberTypeIds.size() + membersCount); + if (Refl.MemberTypeIds.size() >= uint32_t(1u << 24)) + throw std::invalid_argument("Members out of bounds"); + } + // Initialize member types (because it causes recursion) membersCount = 0; @@ -805,9 +831,6 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, if (!fieldDecl) continue; - assert(Refl.MemberTypeIds.size() <= (uint32_t)-1 && - "Members out of bounds"); - Refl.MemberTypeIds[membersOffset + membersCount] = GenerateTypeInfo(ASTCtx, Refl, fieldDecl->getType(), DefaultRowMaj); @@ -894,16 +917,17 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, break; default: - assert(false && "Invalid builtin type"); - break; + throw std::invalid_argument("Invalid builtin type"); } } //Insert - assert(Refl.Types.size() < uint32_t(-1) && "Type id out of bounds"); + if (Refl.Types.size() >= uint32_t(-1)) + throw std::invalid_argument("Type id out of bounds"); - assert(interfaces.size() < uint8_t(-1) && "Only allowing 256 interfaces"); + if (interfaces.size() >= uint8_t(-1)) + throw std::invalid_argument("Only allowing 256 interfaces"); uint32_t interfaceOffset = 0; uint8_t interfaceCount = 0; @@ -963,8 +987,9 @@ static void FillReflectionRegisterAt( DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, + uint32_t nodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), + ValDesc, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, uint32_t(Refl.Registers.size())); uint32_t arrayId = PushArray(Refl, ArraySizeFlat, ArraySize); @@ -1078,7 +1103,9 @@ uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, uint32_t NodeId, D3D_CBUFFER_TYPE Type, bool DefaultRowMaj) { - assert(Refl.Buffers.size() < uint32_t(-1) && "Buffer id out of bounds"); + if (Refl.Buffers.size() >= uint32_t(-1)) + throw std::invalid_argument("Buffer id out of bounds"); + uint32_t bufferId = uint32_t(Refl.Buffers.size()); RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), DefaultRowMaj, NodeId); @@ -1286,8 +1313,8 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, {EnumValue->getInitVal().getSExtValue(), childNodeId}); } - assert(Refl.EnumValues.size() < (uint32_t)(1 << 30) && - "Enum values overflow"); + if (Refl.EnumValues.size() >= uint32_t(1 << 30)) + throw std::invalid_argument("Enum values overflow"); QualType enumType = Enum->getIntegerType(); QualType desugared = enumType.getDesugaredType(ASTCtx); @@ -1453,30 +1480,40 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, } } -DxcHLSLReflectionData::DxcHLSLReflectionData(clang::CompilerInstance &Compiler, - clang::TranslationUnitDecl &Ctx, - uint32_t AutoBindingSpace, - D3D12_HLSL_REFLECTION_FEATURE Features, - bool DefaultRowMaj) { +bool DxcHLSLReflectionData::Initialize(clang::CompilerInstance &Compiler, + clang::TranslationUnitDecl &Ctx, + uint32_t AutoBindingSpace, + D3D12_HLSL_REFLECTION_FEATURE Features, + bool DefaultRowMaj, + DxcHLSLReflectionData &Result) { DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); const SourceManager &SM = Compiler.getSourceManager(); - *this = {}; - this->Features = Features; + Result = {}; + Result.Features = Features; if (Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { - Strings.push_back(""); - StringsToId[""] = 0; - NodeSymbols.push_back(DxcHLSLNodeSymbol(0, 0, 0, 0, 0, 0)); + Result.Strings.push_back(""); + Result.StringsToId[""] = 0; + Result.NodeSymbols.push_back(DxcHLSLNodeSymbol(0, 0, 0, 0, 0, 0)); } - Nodes.push_back(DxcHLSLNode{D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, 0, 0, - 0xFFFF, 0, uint16_t(-1)}); + Result.Nodes.push_back(DxcHLSLNode{D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, + 0, 0, 0xFFFF, 0, uint16_t(-1)}); + + try { - std::unordered_map fwdDecls; - RecursiveReflectHLSL(Ctx, Compiler.getASTContext(), Diags, SM, *this, - AutoBindingSpace, 0, Features, 0, DefaultRowMaj, fwdDecls); + std::unordered_map fwdDecls; + RecursiveReflectHLSL(Ctx, Compiler.getASTContext(), Diags, SM, Result, + AutoBindingSpace, 0, Features, 0, DefaultRowMaj, + fwdDecls); + return true; + + } catch (const std::invalid_argument &arg) { + llvm::errs() << "DxcHLSLReflectionData::Initialize: Failed " << arg.what(); + return false; + } } //TODO: Debug print code diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 98a96b5187..044a841794 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1037,7 +1037,6 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { //Helper for conversion between symbol names // TODO: GetFunctionParameter - // TODO: types, arrays STDMETHOD(GetNodeByName) (THIS_ _In_ LPCSTR Name, _Out_ UINT *pNodeId) override { @@ -1455,9 +1454,11 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, if (!opts.ReflOpt.DisableSymbols) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - DxcHLSLReflectionData refl(astHelper.compiler, *astHelper.tu, - opts.AutoBindingSpace, reflectMask, - opts.DefaultRowMajor); + DxcHLSLReflectionData refl; + + if (!refl.Initialize(astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, + reflectMask, opts.DefaultRowMajor, refl)) + throw std::exception("refl.Initialize failed"); //TODO: Debug @@ -1470,7 +1471,8 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, DxcHLSLReflectionData deserialized(bytes, true); - assert(deserialized == refl && "Dump or Deserialize doesn't match"); + if (!(deserialized == refl)) + throw std::exception("Dump or Deserialize doesn't match"); printf("Reflection size: %" PRIu64 "\n", bytes.size()); @@ -1483,7 +1485,8 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, DxcHLSLReflectionData deserialized2 = DxcHLSLReflectionData(bytes, false); - assert(deserialized2 == refl && "Dump or Deserialize doesn't match"); + if (!(deserialized2 == refl)) + throw std::exception("Dump or Deserialize doesn't match"); printf("Stripped reflection size: %" PRIu64 "\n", bytes.size()); From a5f34e09891ee54169dbe103b343786f5155cc89 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 27 Sep 2025 22:42:35 +0200 Subject: [PATCH 050/126] Added logic to prune the template arguments from builtin HLSL types as long as no syntax sugar is used to hide the real type --- .../tools/dxcreflection/DxcReflection.cpp | 91 ++++++++++++------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 8424971817..5ada2c310f 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -613,13 +613,61 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, PrintingPolicy policy(ASTCtx.getLangOpts()); policy.SuppressScope = false; policy.AnonymousTagLocations = false; - policy.SuppressTagKeyword = true; - - std::string name = forName.getUnqualifiedType().getAsString(policy); + policy.SuppressTagKeyword = true; + + std::string typeName = forName.getUnqualifiedType().getAsString(policy); + + //Prune template instantiation from type name for builtin types (ex. vector & matrix) + //But only if it's not a sugared type: + // typedef ConstantBuffer MyTest; + //In this case, MyTest will still be seen as a ConstantBuffer but the typeName is MyTest. + + forName = forName.getUnqualifiedType(); + + static const std::unordered_map + lookup = std::unordered_map{ + {{"vector", D3D_SHADER_VARIABLE_TYPE(-1)}, + {"matrix", D3D_SHADER_VARIABLE_TYPE(-2)}, + {"Texture1D", D3D_SVT_TEXTURE1D}, + {"Texture2D", D3D_SVT_TEXTURE2D}, + {"RWTexture1D", D3D_SVT_RWTEXTURE1D}, + {"RWTexture2D", D3D_SVT_RWTEXTURE2D}, + {"Texture2DMS", D3D_SVT_TEXTURE2DMS}, + {"Texture3D", D3D_SVT_TEXTURE3D}, + {"RWTexture3D", D3D_SVT_RWTEXTURE3D}, + {"TextureCube", D3D_SVT_TEXTURECUBE}, + {"Texture1DArray", D3D_SVT_TEXTURE1DARRAY}, + {"Texture2DArray", D3D_SVT_TEXTURE2DARRAY}, + {"RWTexture1DArray", D3D_SVT_RWTEXTURE1DARRAY}, + {"RWTexture2DArray", D3D_SVT_RWTEXTURE2DARRAY}, + {"Texture2DMSArray", D3D_SVT_TEXTURE2DMSARRAY}, + {"TextureCubeArray", D3D_SVT_TEXTURECUBEARRAY}, + {"SamplerState", D3D_SVT_SAMPLER}, + {"ByteAddressBuffer", D3D_SVT_BYTEADDRESS_BUFFER}, + {"RWByteAddressBuffer", D3D_SVT_RWBYTEADDRESS_BUFFER}, + {"StructuredBuffer", D3D_SVT_STRUCTURED_BUFFER}, + {"RWStructuredBuffer", D3D_SVT_RWSTRUCTURED_BUFFER}, + {"AppendStructuredBuffer", D3D_SVT_APPEND_STRUCTURED_BUFFER}, + {"ConsumeStructuredBuffer", D3D_SVT_CONSUME_STRUCTURED_BUFFER}, + {"RWBuffer", D3D_SVT_RWBUFFER}, + {"Buffer", D3D_SVT_BUFFER}, + {"ConstantBuffer", D3D_SVT_CBUFFER}}}; + + if (const TemplateSpecializationType *spec = + dyn_cast(forName.getTypePtr())) { + + const TemplateDecl *td = spec->getTemplateName().getAsTemplateDecl(); + + if (td) { + + auto it = lookup.find(td->getName()); + + if (it != lookup.end() && it->second >= 0) + typeName = it->first; + } + } bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - uint32_t nameId = - hasSymbols ? RegisterString(Refl, name, false) : uint32_t(-1); uint32_t arrayId = PushArray(Refl, arraySize, arrayElem); uint32_t elementsOrArrayId = 0; @@ -659,36 +707,6 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, RecordDecl *recordDecl = record->getDecl(); - static const std::unordered_map - lookup = std::unordered_map{{ - {"vector", D3D_SHADER_VARIABLE_TYPE(-1)}, - {"matrix", D3D_SHADER_VARIABLE_TYPE(-2)}, - {"Texture1D", D3D_SVT_TEXTURE1D}, - {"Texture2D", D3D_SVT_TEXTURE2D}, - {"RWTexture1D", D3D_SVT_RWTEXTURE1D}, - {"RWTexture2D", D3D_SVT_RWTEXTURE2D}, - {"Texture2DMS", D3D_SVT_TEXTURE2DMS}, - {"Texture3D", D3D_SVT_TEXTURE3D}, - {"RWTexture3D", D3D_SVT_RWTEXTURE3D}, - {"TextureCube", D3D_SVT_TEXTURECUBE}, - {"Texture1DArray", D3D_SVT_TEXTURE1DARRAY}, - {"Texture2DArray", D3D_SVT_TEXTURE2DARRAY}, - {"RWTexture1DArray", D3D_SVT_RWTEXTURE1DARRAY}, - {"RWTexture2DArray", D3D_SVT_RWTEXTURE2DARRAY}, - {"Texture2DMSArray", D3D_SVT_TEXTURE2DMSARRAY}, - {"TextureCubeArray", D3D_SVT_TEXTURECUBEARRAY}, - {"SamplerState", D3D_SVT_SAMPLER}, - {"ByteAddressBuffer", D3D_SVT_BYTEADDRESS_BUFFER}, - {"RWByteAddressBuffer", D3D_SVT_RWBYTEADDRESS_BUFFER}, - {"StructuredBuffer", D3D_SVT_STRUCTURED_BUFFER}, - {"RWStructuredBuffer", D3D_SVT_RWSTRUCTURED_BUFFER}, - {"AppendStructuredBuffer", D3D_SVT_APPEND_STRUCTURED_BUFFER}, - {"ConsumeStructuredBuffer", D3D_SVT_CONSUME_STRUCTURED_BUFFER}, - {"RWBuffer", D3D_SVT_RWBUFFER}, - {"Buffer", D3D_SVT_BUFFER}, - {"ConstantBuffer", D3D_SVT_CBUFFER} - }}; - if (const ClassTemplateSpecializationDecl *templateClass = dyn_cast(recordDecl)) { @@ -936,6 +954,9 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, DxcHLSLType hlslType(baseType, elementsOrArrayId, cls, type, rows, columns, membersCount, membersOffset, interfaceOffset, interfaceCount); + uint32_t nameId = + hasSymbols ? RegisterString(Refl, typeName, false) : uint32_t(-1); + uint32_t i = 0; uint32_t j = uint32_t(Refl.Types.size()); From 07db5f37eadc62a78b5437714628cf3d0acff7c9 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 1 Oct 2025 01:08:15 +0200 Subject: [PATCH 051/126] Added parameters to backend; they're quite simple, just a type and interpolation/parameter flags. Fixed in/out parameters having a & in their name and type. Added inner type for resources such as textures and buffers. Added extra validation. --- include/dxc/DxcReflection/DxcReflection.h | 33 +-- include/dxc/dxctools.h | 4 +- .../tools/dxcreflection/DxcReflection.cpp | 256 ++++++++++++++---- 3 files changed, 223 insertions(+), 70 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 26506694bd..16db8174ef 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -264,22 +264,22 @@ struct DxcHLSLEnumValue { } }; -/* -struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC (ex. - // First(In/Out)(Register/Component)), but with - // std::string and NodeId - - std::string SemanticName; - D3D_SHADER_VARIABLE_TYPE Type; // Element type. - D3D_SHADER_VARIABLE_CLASS Class; // Scalar/Vector/Matrix. - uint32_t Rows; // Rows are for matrix parameters. - uint32_t Columns; // Components or Columns in matrix. - D3D_INTERPOLATION_MODE InterpolationMode; // Interpolation mode. - D3D_PARAMETER_FLAGS Flags; // Parameter modifiers. + +struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC without duplicating + // data (typeId holds some) + + uint32_t TypeId; uint32_t NodeId; - // TODO: Array info -};*/ + uint8_t InterpolationMode; // D3D_INTERPOLATION_MODE + uint8_t Flags; // D3D_PARAMETER_FLAGS + uint16_t Padding; + + bool operator==(const DxcHLSLParameter &other) const { + return TypeId == other.TypeId && NodeId == other.NodeId && + InterpolationMode == other.InterpolationMode && Flags == other.Flags; + } +}; struct DxcHLSLFunction { @@ -541,7 +541,7 @@ struct DxcHLSLReflectionData { std::vector Enums; std::vector EnumValues; - // std::vector Parameters; + std::vector Parameters; std::vector Annotations; std::vector Arrays; @@ -587,7 +587,8 @@ struct DxcHLSLReflectionData { Annotations == Other.Annotations && Arrays == Other.Arrays && ArraySizes == Other.ArraySizes && MemberTypeIds == Other.MemberTypeIds && TypeList == Other.TypeList && - Types == Other.Types && Buffers == Other.Buffers; + Types == Other.Types && Buffers == Other.Buffers && + Parameters == Other.Parameters; } bool operator==(const DxcHLSLReflectionData &Other) const { diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 98402794d9..1a54ca9873 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -183,15 +183,15 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE, D3D12_HLSL_NODE_TYPE_INTERFACE, + D3D12_HLSL_NODE_TYPE_PARAMETER, // TODO: D3D12_HLSL_NODE_TYPE_USING, - // TODO: D3D12_HLSL_NODE_TYPE_PARAMETER, D3D12_HLSL_NODE_TYPE_RESERVED = 1 << 7, // Highest bit; reserved as an indicator for fwd declarations D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_INTERFACE + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_PARAMETER }; struct D3D12_HLSL_NODE { diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 5ada2c310f..9c6a9f8271 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -594,7 +594,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, // Unwrap array uint32_t arraySize = 1; - QualType underlying = Original, forName = Original; + QualType underlying = Original, forName = Original.getNonReferenceType(); std::vector arrayElem; while (const ConstantArrayType *arr = @@ -602,11 +602,11 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, uint32_t current = arr->getSize().getZExtValue(); arrayElem.push_back(current); arraySize *= arr->getSize().getZExtValue(); - forName = arr->getElementType(); + forName = arr->getElementType().getNonReferenceType(); underlying = forName.getCanonicalType(); } - underlying = underlying.getCanonicalType(); + underlying = underlying.getNonReferenceType().getCanonicalType(); // Name; Omit struct, class and const keywords @@ -615,7 +615,8 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, policy.AnonymousTagLocations = false; policy.SuppressTagKeyword = true; - std::string typeName = forName.getUnqualifiedType().getAsString(policy); + std::string typeName = + forName.getUnqualifiedType().getAsString(policy); //Prune template instantiation from type name for builtin types (ex. vector & matrix) //But only if it's not a sugared type: @@ -705,7 +706,10 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, bool standardType = false; - RecordDecl *recordDecl = record->getDecl(); + RecordDecl *recordDecl = record->getDecl(); + + QualType innerType; + std::string innerTypeName; //$Element or T depending on type if (const ClassTemplateSpecializationDecl *templateClass = dyn_cast(recordDecl)) { @@ -760,8 +764,20 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, } else { + type = svt; cls = D3D_SVC_OBJECT; + + innerTypeName = "$Element"; + + const TemplateSpecializationType *templateDesc = + forName->getAs(); + + assert(templateDesc && "Expected a valid TemplateSpecializationType"); + innerType = templateDesc->getArg(0).getAsType(); + + if (svt == D3D_SVT_RWBUFFER || svt == D3D_SVT_BUFFER || svt == D3D_SVT_CBUFFER) + innerTypeName = innerType.getUnqualifiedType().getAsString(policy); } } } @@ -778,6 +794,25 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, } } + // Buffer types have a member to allow inspection of the types + + if (innerTypeName.size()) { + + uint32_t nameId = hasSymbols ? RegisterString(Refl, innerTypeName, false) + : uint32_t(-1); + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, innerType, DefaultRowMaj); + + membersOffset = uint32_t(Refl.MemberTypeIds.size()); + membersCount = 1; + + Refl.MemberTypeIds.push_back(typeId); + + if (hasSymbols) + Refl.MemberNameIds.push_back(nameId); + } + // Fill members if (!standardType && recordDecl->isCompleteDefinition() && cls != D3D_SVC_OBJECT) { @@ -1136,54 +1171,84 @@ uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, return bufferId; } -/* TODO: -static void AddFunctionParameters(ASTContext &ASTCtx, QualType Type, Decl *Decl, - DxcHLSLReflectionData &Refl, const SourceManager &SM, - uint32_t ParentNodeId) { +//DxilInterpolationMode.cpp but a little bit cleaned up +static D3D_INTERPOLATION_MODE GetInterpolationMode(Decl *decl) { - PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); + if (!decl) //Return type + return D3D_INTERPOLATION_UNDEFINED; - QualType desugared = Type.getDesugaredType(ASTCtx); + bool bNoInterpolation = decl->hasAttr(); + bool bLinear = decl->hasAttr(); + bool bNoperspective = decl->hasAttr(); + bool bCentroid = decl->hasAttr(); + bool bSample = decl->hasAttr(); - PrintfStream str; - desugared.print(str, printingPolicy); + uint8_t mask = uint8_t(bNoInterpolation) << 4; + mask |= uint8_t(bLinear) << 3; + mask |= uint8_t(bNoperspective) << 2; + mask |= uint8_t(bCentroid) << 1; + mask |= uint8_t(bSample); - if (Decl) - Decl->print(str); + if (mask > 16) + return D3D_INTERPOLATION_UNDEFINED; + + static constexpr const D3D_INTERPOLATION_MODE modes[] = { + D3D_INTERPOLATION_UNDEFINED, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_CENTROID, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_LINEAR, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_CENTROID, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_CONSTANT + }; - //Generate parameter + return modes[mask]; +} + +static void AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, + DxcHLSLReflectionData &Refl, + const SourceManager &SM, uint32_t ParentNodeId, + bool DefaultRowMaj) { + + PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); + + uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, Type, DefaultRowMaj); uint32_t nodeId = PushNextNodeId( Refl, SM, ASTCtx.getLangOpts(), Decl && dyn_cast(Decl) ? dyn_cast(Decl)->getName() : "", Decl, D3D12_HLSL_NODE_TYPE_PARAMETER, ParentNodeId, - (uint32_t)Refl.Parameters.size()); + uint32_t(Refl.Parameters.size())); - std::string semanticName; + D3D_INTERPOLATION_MODE interpolationMode = GetInterpolationMode(Decl); + D3D_PARAMETER_FLAGS flags = D3D_PF_NONE; - if (NamedDecl *ValDesc = dyn_cast(Decl)) { + if (Decl) { - ArrayRef UA = ValDesc->getUnusualAnnotations(); + if (Decl->hasAttr()) + flags = D3D_PARAMETER_FLAGS(flags | D3D_PF_IN); - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) { + if (Decl->hasAttr()) + flags = D3D_PARAMETER_FLAGS(flags | D3D_PF_OUT); - if ((*It)->getKind() != hlsl::UnusualAnnotation::UA_SemanticDecl) - continue; - - semanticName = cast(*It)->SemanticName; - } + if (Decl->hasAttr()) + flags = D3D_PARAMETER_FLAGS(flags | D3D_PF_IN | D3D_PF_OUT); } - DxcHLSLParameter parameter{std::move(semanticName)}; - - type, clss, rows, columns, interpolationMode, flags; - parameter.NodeId = nodeId; - - Refl.Parameters.push_back(parameter); - - //It's a struct, add parameters recursively -}*/ + Refl.Parameters.push_back( + DxcHLSLParameter{typeId, nodeId, uint8_t(interpolationMode), uint8_t(flags)}); +} static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, @@ -1269,19 +1334,18 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, !Func->getReturnType().getTypePtr()->isVoidType(), hasDefinition}; - // TODO: - /* - for (uint32_t i = 0; i < func.NumParameters; ++i) - AddFunctionParameters(ASTCtx, Func->getParamDecl(i)->getType(), - Func->getParamDecl(i), Refl, SM, nodeId); + for (uint32_t i = 0; i < func.GetNumParameters(); ++i) + AddFunctionParameter(ASTCtx, Func->getParamDecl(i)->getType(), + Func->getParamDecl(i), Refl, SM, nodeId, + DefaultRowMaj); - if (func.HasReturn) - AddFunctionParameters(ASTCtx, Func->getReturnType(), nullptr, Refl, SM, - nodeId);*/ + if (func.HasReturn()) + AddFunctionParameter(ASTCtx, Func->getReturnType(), nullptr, Refl, SM, + nodeId, DefaultRowMaj); Refl.Functions.push_back(std::move(func)); - //TODO: + //TODO: Scopes /*if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, @@ -1569,7 +1633,7 @@ static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { static const char *arr[] = {"Register", "Function", "Enum", "EnumValue", "Namespace", "Variable", "Typedef", "Struct", "Union", - "StaticVariable", "Interface"}; + "StaticVariable", "Interface", "Parameter"}; return arr[uint32_t(type)]; } @@ -1816,6 +1880,36 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, // TODO: case D3D12_HLSL_NODE_TYPE_USING: + case D3D12_HLSL_NODE_TYPE_PARAMETER: { + + const DxcHLSLParameter ¶m = Refl.Parameters[localId]; + + if (param.InterpolationMode || param.Flags) { + + static const char *inouts[] = {NULL, "in", "out", "inout"}; + const char *inout = inouts[param.Flags]; + + static const char *interpolationModes[] = { + "", + "Constant", + "Linear", + "LinearCentroid", + "LinearNoPerspective", + "LinearNoPerspectiveCentroid", + "LinearSample", + "LinearNoPerspectiveSample"}; + + const char *interpolationMode = + interpolationModes[param.InterpolationMode]; + + printf("%s%s%s\n", std::string(Depth, '\t').c_str(), inout ? inout : "", + ((inout ? " " : "") + std::string(interpolationMode)).c_str()); + } + + typeToPrint = param.TypeId; + break; + } + case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: @@ -1890,7 +1984,7 @@ struct DxcHLSLHeader { uint32_t Buffers; uint32_t TypeListCount; - uint32_t Padding; + uint32_t Parameters; }; template @@ -2148,7 +2242,7 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, - Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, TypeNameIds, Buffers); + Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, TypeNameIds, Buffers, Parameters); Bytes.resize(toReserve); @@ -2163,14 +2257,15 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { uint32_t(EnumValues.size()), uint32_t(Annotations.size()), uint32_t(Arrays.size()), uint32_t(ArraySizes.size()), uint32_t(MemberTypeIds.size()), uint32_t(Types.size()), - uint32_t(Buffers.size()), uint32_t(TypeList.size())}; + uint32_t(Buffers.size()), uint32_t(TypeList.size()), + uint32_t(Parameters.size())}; toReserve += sizeof(DxcHLSLHeader); Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, - TypeNameIds, Buffers); + TypeNameIds, Buffers, Parameters); } DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes, @@ -2204,7 +2299,8 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes Annotations, header.Annotations, ArraySizes, header.ArraySizes, Arrays, header.Arrays, MemberTypeIds, header.Members, TypeList, header.TypeListCount, MemberNameIds, memberSymbolCount, Types, - header.Types, TypeNameIds, typeSymbolCount, Buffers, header.Buffers); + header.Types, TypeNameIds, typeSymbolCount, Buffers, header.Buffers, + Parameters, header.Parameters); // Validation errors are throws to prevent accessing invalid data @@ -2243,10 +2339,12 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_REGISTER: maxValue = header.Registers; break; + case D3D12_HLSL_NODE_TYPE_FUNCTION: maxValue = header.Functions; allowFwdDeclare = true; break; + case D3D12_HLSL_NODE_TYPE_ENUM: maxValue = header.Enums; allowFwdDeclare = true; @@ -2255,6 +2353,18 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes maxValue = header.EnumValues; break; + case D3D12_HLSL_NODE_TYPE_PARAMETER: + + maxValue = header.Parameters; + + if (Nodes[node.GetParentId()].GetNodeType() != + D3D12_HLSL_NODE_TYPE_FUNCTION) + throw std::invalid_argument( + "Node " + std::to_string(i) + + " is a parameter but parent isn't a function"); + + break; + // TODO: case D3D12_HLSL_NODE_TYPE_USING: case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: @@ -2270,6 +2380,18 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes break; } + switch (node.GetNodeType()) { + + case D3D12_HLSL_NODE_TYPE_TYPEDEF: + case D3D12_HLSL_NODE_TYPE_VARIABLE: + case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: + case D3D12_HLSL_NODE_TYPE_PARAMETER: + if (node.GetChildCount()) + throw std::invalid_argument("Node " + std::to_string(i) + + " is a parameter, typedef, variable or " + "static variable but also has children"); + } + if ((node.GetNodeType() == D3D12_HLSL_NODE_TYPE_REGISTER || node.GetNodeType() == D3D12_HLSL_NODE_TYPE_VARIABLE) && Nodes[node.GetParentId()].GetNodeType() == @@ -2319,8 +2441,8 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes } } - for(uint32_t i = 0; i < header.Functions; ++i) { - + for (uint32_t i = 0; i < header.Functions; ++i) { + const DxcHLSLFunction &func = Functions[i]; if (func.NodeId >= header.Nodes || @@ -2328,6 +2450,20 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes Nodes[func.NodeId].GetLocalId() != i) throw std::invalid_argument("Function " + std::to_string(i) + " points to an invalid nodeId"); + + uint32_t paramCount = func.GetNumParameters() + func.HasReturn(); + + if (Nodes[func.NodeId].GetChildCount() < paramCount) + throw std::invalid_argument("Function " + std::to_string(i) + + " is missing parameters and/or return"); + + for (uint32_t j = 0; j < paramCount; ++j) + if (Nodes[func.NodeId + 1 + j].GetParentId() != func.NodeId || + Nodes[func.NodeId + 1 + j].GetNodeType() != + D3D12_HLSL_NODE_TYPE_PARAMETER) + throw std::invalid_argument( + "Function " + std::to_string(i) + + " is missing valid parameters and/or return"); } for(uint32_t i = 0; i < header.Enums; ++i) { @@ -2433,6 +2569,22 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (TypeList[i] >= header.Types) throw std::invalid_argument("Type list index " + std::to_string(i) + " points to an invalid type"); + + for (uint32_t i = 0; i < header.Parameters; ++i) { + + const DxcHLSLParameter ¶m = Parameters[i]; + + if (param.NodeId >= header.Nodes || + Nodes[param.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_PARAMETER || + Nodes[param.NodeId].GetLocalId() != i || param.TypeId >= header.Types) + throw std::invalid_argument("Parameter " + std::to_string(i) + + " points to an invalid nodeId"); + + if (param.Flags > 3 || + param.InterpolationMode > D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE) + throw std::invalid_argument("Parameter " + std::to_string(i) + + " has invalid data"); + } for (uint32_t i = 0; i < header.Types; ++i) { From 64fb5663eaf1c6354641be60c7bf90579fbce09f Mon Sep 17 00:00:00 2001 From: NielsbishereAlt Date: Fri, 3 Oct 2025 14:06:35 +0200 Subject: [PATCH 052/126] Added function parameters to frontend. --- include/dxc/dxctools.h | 3 +- tools/clang/tools/libclang/dxcreflector.cpp | 100 ++++++++++++++++++-- 2 files changed, 95 insertions(+), 8 deletions(-) diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 1a54ca9873..25c7fe7dbe 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -261,10 +261,9 @@ DECLARE_INTERFACE(IDxcHLSLReflection) { (THIS_ _In_ UINT FunctionIndex, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) PURE; - /*TODO: // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) - (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE;*/ + (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE; STDMETHOD(GetStructTypeByIndex) (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 044a841794..ed4c113bb4 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -347,6 +347,53 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { } }; +class CHLSLFunctionParameter final : public ID3D12FunctionParameterReflection { + +protected: + const DxcHLSLReflectionData *m_Data = nullptr; + uint32_t m_NodeId = 0; + +public: + CHLSLFunctionParameter() = default; + + void Initialize(const DxcHLSLReflectionData &Data, uint32_t NodeId) { + m_Data = &Data; + m_NodeId = NodeId; + } + + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_PARAMETER_DESC *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + const DxcHLSLNode &node = m_Data->Nodes[m_NodeId]; + + LPCSTR semanticName = + node.GetSemanticId() == uint32_t(-1) + ? "" + : m_Data->StringsNonDebug[node.GetSemanticId()].c_str(); + + LPCSTR name = + m_Data->Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + ? m_Data->Strings[m_Data->NodeSymbols[m_NodeId].NameId].c_str() + : ""; + + const DxcHLSLParameter ¶m = m_Data->Parameters[node.GetLocalId()]; + const DxcHLSLType &type = m_Data->Types[param.TypeId]; + + *pDesc = + D3D12_PARAMETER_DESC{name, + semanticName, + D3D_SHADER_VARIABLE_TYPE(type.Type), + D3D_SHADER_VARIABLE_CLASS(type.Class), + type.Rows, + type.Columns, + D3D_INTERPOLATION_MODE(param.InterpolationMode), + D3D_PARAMETER_FLAGS(param.Flags)}; + + return S_OK; + } +}; + class CHLSLReflectionVariable final : public ID3D12ShaderReflectionVariable { protected: CHLSLReflectionType *m_pType; @@ -577,6 +624,9 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { std::unordered_map NameToNonFwdIds[int(FwdDeclType::COUNT)]; + std::vector NodeToParameterId; + std::vector FunctionParameters; + DxcHLSLReflection() = default; void Finalize() { @@ -589,6 +639,11 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { bool hasSymbols = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; std::vector globalVars; + NodeToParameterId.resize(Data.Nodes.size()); + + std::vector functionParameters; + functionParameters.reserve(Data.Nodes.size() / 4); + for (uint32_t i = 0; i < uint32_t(Data.Nodes.size()); ++i) { const DxcHLSLNode &node = Data.Nodes[i]; @@ -597,6 +652,11 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { !node.GetParentId()) globalVars.push_back(i); + if (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_PARAMETER) { + NodeToParameterId[i] = uint32_t(functionParameters.size()); + functionParameters.push_back(i); + } + // Filter out fwd declarations for structs, unions, interfaces, functions, enums if (!node.IsFwdDeclare()) { @@ -666,6 +726,11 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { for (uint32_t i = 0; i < (uint32_t)Data.Types.size(); ++i) Types[i].Initialize(Data, i, Types); + FunctionParameters.resize(functionParameters.size()); + + for (uint32_t i = 0; i < uint32_t(functionParameters.size()); ++i) + FunctionParameters[i].Initialize(Data, functionParameters[i]); + for (uint32_t i = 0; i < (uint32_t)Data.Buffers.size(); ++i) { ConstantBuffers[i].Initialize(Data, Data.Buffers[i].NodeId, @@ -699,6 +764,9 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { NameToNonFwdIds[i] = std::move(moved.NameToNonFwdIds[i]); } + NodeToParameterId = std::move(moved.NodeToParameterId); + FunctionParameters = std::move(moved.FunctionParameters); + return *this; } @@ -969,10 +1037,32 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { return S_OK; } - //TODO: - //// Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. - //STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) - //(THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE; + // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. + STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) + (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) override { + + if (FunctionIndex >= Data.Functions.size()) + return nullptr; + + const DxcHLSLFunction &func = Data.Functions[FunctionIndex]; + + if (ParameterIndex == D3D_RETURN_PARAMETER_INDEX) { + + if (!func.HasReturn()) + return nullptr; + + uint32_t parameterId = + NodeToParameterId[func.NodeId + 1 + func.GetNumParameters()]; + + return &FunctionParameters[parameterId]; + } + + if (uint32_t(ParameterIndex) >= func.GetNumParameters()) + return nullptr; + + uint32_t parameterId = NodeToParameterId[func.NodeId + 1 + ParameterIndex]; + return &FunctionParameters[parameterId]; + } STDMETHOD(GetStructTypeByIndex) (THIS_ _In_ UINT Index, @@ -1036,8 +1126,6 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { //Helper for conversion between symbol names - // TODO: GetFunctionParameter - STDMETHOD(GetNodeByName) (THIS_ _In_ LPCSTR Name, _Out_ UINT *pNodeId) override { From 155955227214069ebf79788b35efd5555685933d Mon Sep 17 00:00:00 2001 From: NielsbishereAlt Date: Fri, 3 Oct 2025 14:27:26 +0200 Subject: [PATCH 053/126] Added scopes; the inner body of functions can now be reflected. --- include/dxc/Support/HLSLOptions.td | 2 +- include/dxc/dxctools.h | 4 ++-- tools/clang/tools/dxcreflection/DxcReflection.cpp | 14 +++++++++----- tools/clang/tools/libclang/dxcreflector.cpp | 4 ++-- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index 5a68f53c6b..0ec05fdbac 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -577,7 +577,7 @@ def reflect_namespaces : Flag<["-", "/"], "reflect-namespaces">, Group, Group, Flags<[ReflectOption]>, HelpText<"Reflect HLSL user types (typedef, using, struct, enum).">; def reflect_scopes : Flag<["-", "/"], "reflect-scopes">, Group, Flags<[ReflectOption]>, - HelpText<"Reflect HLSL scopes (variables and structs defined in functions, structs and scopes).">; + HelpText<"Reflect HLSL scopes (variables and structs defined in functions).">; def reflect_disable_symbols : Flag<["-", "/"], "reflect-disable-symbols">, Group, Flags<[ReflectOption]>, HelpText<"Reflect HLSL disable symbols.">; diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 25c7fe7dbe..0fc5693c06 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -90,8 +90,8 @@ enum D3D12_HLSL_REFLECTION_FEATURE { // Include user types (struct, enum, typedef, etc.) D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES = 1 << 3, - // Variables, structs, functions defined in functions, scopes & structs - //TODO: D3D12_HLSL_REFLECTION_FEATURE_SCOPES = 1 << 4, + // Variables, structs, functions defined in functions + D3D12_HLSL_REFLECTION_FEATURE_SCOPES = 1 << 4, // Symbol info (stripping this will remove names and file location info) D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO = 1 << 16, diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 9c6a9f8271..7d55455a9e 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1280,6 +1280,9 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) //TODO: We might want to include these for a more complete picture. continue; + if (isa(it)) //Skip parameters, already handled explicitly + continue; + if (HLSLBufferDecl *CBuffer = dyn_cast(it)) { if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) @@ -1345,12 +1348,11 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, Refl.Functions.push_back(std::move(func)); - //TODO: Scopes - /*if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { + if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, - nodeId, DefaultRowMaj); - }*/ + nodeId, DefaultRowMaj, FwdDecls); + } } else if (TypedefDecl *Typedef = dyn_cast(it)) { @@ -1480,7 +1482,9 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, // Handle $Globals - if (varDecl && Depth == 0 && !varDecl->hasAttr()) { + if (varDecl && + (Depth == 0 || Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES) && + !varDecl->hasAttr()) { const std::string &name = ValDecl->getName(); diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index ed4c113bb4..385711d297 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1533,8 +1533,8 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, if (opts.ReflOpt.UserTypes) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES; - //TODO: if (opts.ReflOpt.Scopes) - // reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SCOPES; + if (opts.ReflOpt.Scopes) + reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SCOPES; if (!reflectMask) reflectMask = D3D12_HLSL_REFLECTION_FEATURE_ALL; From 5ef07153d5d0904604d31c19899e66be6518d56a Mon Sep 17 00:00:00 2001 From: NielsbishereAlt Date: Mon, 13 Oct 2025 05:41:05 +0200 Subject: [PATCH 054/126] Added DxcHLSLIf to handle control flow in a function. THe if is quite simple; it stores if it has a condition var, else statement and how many if nodes it contains. Else nodes can be inferred from that. Started handling the inner body of a function, looping through ifs/fors/while/do/switch/decl/scope. Added validation to if statement to ensure we don't load invalid data. --- include/dxc/DxcReflection/DxcReflection.h | 41 +++- include/dxc/dxctools.h | 18 +- .../tools/dxcreflection/DxcReflection.cpp | 196 +++++++++++++++++- 3 files changed, 237 insertions(+), 18 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 16db8174ef..90743d8eac 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -281,6 +281,39 @@ struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC without duplicating } }; +struct DxcHLSLIf { + + uint32_t NodeId; + uint32_t HasConditionVar_HasElse_IfNodes; + + DxcHLSLIf() = default; + + DxcHLSLIf(uint32_t NodeId, uint32_t IfNodes, bool HasConditionVar, + bool HasElse) + : NodeId(NodeId), + HasConditionVar_HasElse_IfNodes(IfNodes | + (HasConditionVar ? (1u << 30) : 0) | + (HasElse ? (1u << 31) : 0)) { + if (IfNodes >= (1u << 30)) + throw std::invalid_argument("IfNodes out of bounds"); + } + + uint32_t GetIfNodes() const { + return HasConditionVar_HasElse_IfNodes << 2 >> 2; + } + + bool HasConditionVar() const { + return (HasConditionVar_HasElse_IfNodes >> 30) & 1; + } + + bool HasElse() const { return (HasConditionVar_HasElse_IfNodes >> 31) & 1; } + + bool operator==(const DxcHLSLIf &other) const { + return NodeId == other.NodeId && HasConditionVar_HasElse_IfNodes == + other.HasConditionVar_HasElse_IfNodes; + } +}; + struct DxcHLSLFunction { uint32_t NodeId; @@ -292,8 +325,8 @@ struct DxcHLSLFunction { bool HasDefinition) : NodeId(NodeId), NumParametersHasReturnAndDefinition(NumParameters | - (HasReturn ? (1 << 30) : 0) | - (HasDefinition ? (1 << 31) : 0)) { + (HasReturn ? (1u << 30) : 0) | + (HasDefinition ? (1u << 31) : 0)) { if (NumParameters >= (1u << 30)) throw std::invalid_argument("NumParameters out of bounds"); @@ -552,6 +585,8 @@ struct DxcHLSLReflectionData { std::vector Types; std::vector Buffers; + std::vector Ifs; + // Can be stripped if !(D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) std::vector NodeSymbols; @@ -588,7 +623,7 @@ struct DxcHLSLReflectionData { ArraySizes == Other.ArraySizes && MemberTypeIds == Other.MemberTypeIds && TypeList == Other.TypeList && Types == Other.Types && Buffers == Other.Buffers && - Parameters == Other.Parameters; + Parameters == Other.Parameters && Ifs == Other.Ifs; } bool operator==(const DxcHLSLReflectionData &Other) const { diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 0fc5693c06..3fdf85a8d9 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -176,22 +176,32 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_VARIABLE, // localId points to the type D3D12_HLSL_NODE_TYPE_TYPEDEF, // ^ - D3D12_HLSL_NODE_TYPE_STRUCT, // has Variables as member like buffers do, - // localId is the typeId (if not fwd decl) - D3D12_HLSL_NODE_TYPE_UNION, // ^ + D3D12_HLSL_NODE_TYPE_STRUCT, // has Variables as member like buffers do, + // localId is the typeId (if not fwd decl) + D3D12_HLSL_NODE_TYPE_UNION, // ^ D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE, D3D12_HLSL_NODE_TYPE_INTERFACE, D3D12_HLSL_NODE_TYPE_PARAMETER, + // Control flow, for full inspection of what variables exist where and scopes + + D3D12_HLSL_NODE_TYPE_IF, + // D3D12_HLSL_NODE_TYPE_FOR, + // D3D12_HLSL_NODE_TYPE_SWITCH, + // D3D12_HLSL_NODE_TYPE_DO, + // D3D12_HLSL_NODE_TYPE_SCOPE, + // TODO: D3D12_HLSL_NODE_TYPE_USING, D3D12_HLSL_NODE_TYPE_RESERVED = 1 << 7, // Highest bit; reserved as an indicator for fwd declarations D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_PARAMETER + + // Don't forget to properly update NodeTypeToString + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_IF }; struct D3D12_HLSL_NODE { diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 7d55455a9e..99683a7d4c 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1250,6 +1250,99 @@ static void AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, DxcHLSLParameter{typeId, nodeId, uint8_t(interpolationMode), uint8_t(flags)}); } +static void RecursiveReflectBody(const Stmt *stmt, ASTContext &ASTCtx, + DiagnosticsEngine &Diags, + const SourceManager &SM, + DxcHLSLReflectionData &Refl, + uint32_t AutoBindingSpace, uint32_t Depth, + D3D12_HLSL_REFLECTION_FEATURE Features, + uint32_t ParentNodeId, bool DefaultRowMaj, + std::unordered_map &FwdDecls, + const LangOptions &LangOpts) { + + if (!stmt) + return; + + for (const Stmt *subStmt : stmt->children()) { + + if (!subStmt) + continue; + + if (const IfStmt *If = dyn_cast(subStmt)) { + + uint32_t ifLoc = uint32_t(Refl.Ifs.size()); + Refl.Ifs.push_back(DxcHLSLIf()); + + const SourceRange &sourceRange = If->getSourceRange(); + + uint32_t ifNode = PushNextNodeId(Refl, SM, LangOpts, "", nullptr, + D3D12_HLSL_NODE_TYPE_IF, ParentNodeId, + ifLoc, &sourceRange, &FwdDecls); + + if (VarDecl *varDecl = If->getConditionVariable()) { + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, varDecl->getType(), DefaultRowMaj); + + const SourceRange &sourceRange = varDecl->getSourceRange(); + + PushNextNodeId(Refl, SM, LangOpts, varDecl->getName(), varDecl, + D3D12_HLSL_NODE_TYPE_VARIABLE, ifNode, typeId, + &sourceRange, &FwdDecls); + } + + uint32_t start = uint32_t(Refl.Nodes.size()); + + RecursiveReflectBody(If->getThen(), ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, ifNode, + DefaultRowMaj, FwdDecls, LangOpts); + + uint32_t thenCount = uint32_t(Refl.Nodes.size()) - start; + + RecursiveReflectBody(If->getElse(), ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, ifNode, + DefaultRowMaj, FwdDecls, LangOpts); + + Refl.Ifs[ifLoc] = DxcHLSLIf(ifNode, thenCount, If->getConditionVariable(), + If->getElse()); + } + + else if (const ForStmt *For = dyn_cast(subStmt)) { + // For->getInit(); + // For->getBody(); + } + + else if (const WhileStmt *While = dyn_cast(subStmt)) { + // While->getBody(); + // While->getCond(); + } + + else if (const DoStmt *Do = dyn_cast(subStmt)) { + // Do->getBody(); + } + + else if (const CompoundStmt *Scope = dyn_cast(subStmt)) { + // Scope->body(); + } + + else if (const DeclStmt *DS = dyn_cast(subStmt)) { + for (Decl *D : DS->decls()) { + if (VarDecl *varDecl = llvm::dyn_cast(D)) { + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, varDecl->getType(), DefaultRowMaj); + + const SourceRange &sourceRange = varDecl->getSourceRange(); + + PushNextNodeId(Refl, SM, LangOpts, varDecl->getName(), varDecl, + D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId, + &sourceRange, &FwdDecls); + } + } + } + } +} + static void RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, @@ -1349,9 +1442,10 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, Refl.Functions.push_back(std::move(func)); if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { - RecursiveReflectHLSL(*Definition, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, - nodeId, DefaultRowMaj, FwdDecls); + clang::Stmt *stmt = Func->getBody(); + RecursiveReflectBody(stmt, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, nodeId, DefaultRowMaj, + FwdDecls, ASTCtx.getLangOpts()); } } @@ -1634,10 +1728,10 @@ static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { - static const char *arr[] = {"Register", "Function", "Enum", - "EnumValue", "Namespace", "Variable", - "Typedef", "Struct", "Union", - "StaticVariable", "Interface", "Parameter"}; + static const char *arr[] = { + "Register", "Function", "Enum", "EnumValue", "Namespace", + "Variable", "Typedef", "Struct", "Union", "StaticVariable", + "Interface", "Parameter", "If"}; return arr[uint32_t(type)]; } @@ -1914,6 +2008,20 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, break; } + case D3D12_HLSL_NODE_TYPE_IF: { + + const DxcHLSLIf &If = Refl.Ifs[localId]; + const DxcHLSLNode &Node = Refl.Nodes[If.NodeId]; + + printf("%sif nodes: %u, else nodes: %u%s%s\n", + std::string(Depth, '\t').c_str(), If.GetIfNodes(), + Node.GetChildCount() - If.GetIfNodes() - If.HasConditionVar(), + If.HasConditionVar() ? " (has cond var)" : "", + If.HasElse() ? " (has else)" : ""); + + break; + } + case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: @@ -1989,6 +2097,9 @@ struct DxcHLSLHeader { uint32_t TypeListCount; uint32_t Parameters; + + uint32_t Ifs; + uint32_t Pad; }; template @@ -2246,7 +2357,7 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, - Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, TypeNameIds, Buffers, Parameters); + Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, TypeNameIds, Buffers, Parameters, Ifs); Bytes.resize(toReserve); @@ -2262,14 +2373,14 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { uint32_t(Arrays.size()), uint32_t(ArraySizes.size()), uint32_t(MemberTypeIds.size()), uint32_t(Types.size()), uint32_t(Buffers.size()), uint32_t(TypeList.size()), - uint32_t(Parameters.size())}; + uint32_t(Parameters.size()), uint32_t(Ifs.size())}; toReserve += sizeof(DxcHLSLHeader); Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, - TypeNameIds, Buffers, Parameters); + TypeNameIds, Buffers, Parameters, Ifs); } DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes, @@ -2304,7 +2415,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes Arrays, header.Arrays, MemberTypeIds, header.Members, TypeList, header.TypeListCount, MemberNameIds, memberSymbolCount, Types, header.Types, TypeNameIds, typeSymbolCount, Buffers, header.Buffers, - Parameters, header.Parameters); + Parameters, header.Parameters, Ifs, header.Ifs); // Validation errors are throws to prevent accessing invalid data @@ -2369,6 +2480,19 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes break; + case D3D12_HLSL_NODE_TYPE_IF: + + maxValue = header.Ifs; + + if (Nodes[node.GetParentId()].GetNodeType() != + D3D12_HLSL_NODE_TYPE_FUNCTION && + Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_IF) + throw std::invalid_argument( + "Node " + std::to_string(i) + + " is an if but parent isn't a function or if"); + + break; + // TODO: case D3D12_HLSL_NODE_TYPE_USING: case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: @@ -2589,6 +2713,56 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes throw std::invalid_argument("Parameter " + std::to_string(i) + " has invalid data"); } + + for (uint32_t i = 0; i < header.Ifs; ++i) { + + const DxcHLSLIf &If = Ifs[i]; + + if (If.NodeId >= header.Nodes || + Nodes[If.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_IF || + Nodes[If.NodeId].GetLocalId() != i) + throw std::invalid_argument("If " + std::to_string(i) + + " points to an invalid nodeId"); + + bool ifCondVar = If.HasConditionVar(); + uint32_t minParamCount = If.GetIfNodes() + ifCondVar; + const DxcHLSLNode &node = Nodes[If.NodeId]; + + if (node.GetChildCount() < minParamCount) + throw std::invalid_argument("If " + std::to_string(i) + + " didn't have required child nodes"); + + if (ifCondVar && + Nodes[If.NodeId + 1].GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) + throw std::invalid_argument( + "If " + std::to_string(i) + + " has condition variable but first child is not a variable"); + + // If/Then children could only be + // struct/union/interface/if/variable/typedef/enum (We skip condition var) + + for (uint32_t j = ifCondVar; j < node.GetChildCount(); ++j) { + + const DxcHLSLNode &childNode = Nodes[If.NodeId + 1 + j]; + + switch (childNode.GetNodeType()) { + case D3D12_HLSL_NODE_TYPE_VARIABLE: + case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_STRUCT: + case D3D12_HLSL_NODE_TYPE_UNION: + case D3D12_HLSL_NODE_TYPE_INTERFACE: + case D3D12_HLSL_NODE_TYPE_TYPEDEF: + case D3D12_HLSL_NODE_TYPE_ENUM: + break; + default: + throw std::invalid_argument( + "If " + std::to_string(i) + + " has if/then with children of invalid type"); + } + + j += childNode.GetChildCount(); + } + } for (uint32_t i = 0; i < header.Types; ++i) { From ccf035d8403faf046d2fc09b885237b2fbec1770 Mon Sep 17 00:00:00 2001 From: NielsbishereAlt Date: Mon, 13 Oct 2025 06:32:42 +0200 Subject: [PATCH 055/126] Can now handle scopes inside of a body. It also validates with the same requirements as if. TODO: Make sure that a scope is hidden if it's part of an if/for/etc. --- include/dxc/dxctools.h | 4 +- .../tools/dxcreflection/DxcReflection.cpp | 278 ++++++++++-------- 2 files changed, 157 insertions(+), 125 deletions(-) diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 3fdf85a8d9..57aa606525 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -188,10 +188,10 @@ enum D3D12_HLSL_NODE_TYPE { // Control flow, for full inspection of what variables exist where and scopes D3D12_HLSL_NODE_TYPE_IF, + D3D12_HLSL_NODE_TYPE_SCOPE, // D3D12_HLSL_NODE_TYPE_FOR, // D3D12_HLSL_NODE_TYPE_SWITCH, // D3D12_HLSL_NODE_TYPE_DO, - // D3D12_HLSL_NODE_TYPE_SCOPE, // TODO: D3D12_HLSL_NODE_TYPE_USING, @@ -201,7 +201,7 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, // Don't forget to properly update NodeTypeToString - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_IF + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_SCOPE }; struct D3D12_HLSL_NODE { diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 99683a7d4c..189654eeb3 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1250,94 +1250,96 @@ static void AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, DxcHLSLParameter{typeId, nodeId, uint8_t(interpolationMode), uint8_t(flags)}); } -static void RecursiveReflectBody(const Stmt *stmt, ASTContext &ASTCtx, - DiagnosticsEngine &Diags, - const SourceManager &SM, - DxcHLSLReflectionData &Refl, - uint32_t AutoBindingSpace, uint32_t Depth, - D3D12_HLSL_REFLECTION_FEATURE Features, - uint32_t ParentNodeId, bool DefaultRowMaj, - std::unordered_map &FwdDecls, - const LangOptions &LangOpts) { - - if (!stmt) +static void RecursiveReflectBody( + const Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, + const SourceManager &SM, DxcHLSLReflectionData &Refl, + uint32_t AutoBindingSpace, uint32_t Depth, + D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, + bool DefaultRowMaj, std::unordered_map &FwdDecls, + const LangOptions &LangOpts) { + + if (!Statement) return; - for (const Stmt *subStmt : stmt->children()) { + if (const IfStmt *If = dyn_cast(Statement)) { - if (!subStmt) - continue; + uint32_t ifLoc = uint32_t(Refl.Ifs.size()); + Refl.Ifs.push_back(DxcHLSLIf()); - if (const IfStmt *If = dyn_cast(subStmt)) { + const SourceRange &sourceRange = If->getSourceRange(); - uint32_t ifLoc = uint32_t(Refl.Ifs.size()); - Refl.Ifs.push_back(DxcHLSLIf()); + uint32_t ifNode = + PushNextNodeId(Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_IF, + ParentNodeId, ifLoc, &sourceRange, &FwdDecls); - const SourceRange &sourceRange = If->getSourceRange(); + if (VarDecl *varDecl = If->getConditionVariable()) { - uint32_t ifNode = PushNextNodeId(Refl, SM, LangOpts, "", nullptr, - D3D12_HLSL_NODE_TYPE_IF, ParentNodeId, - ifLoc, &sourceRange, &FwdDecls); + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, varDecl->getType(), DefaultRowMaj); - if (VarDecl *varDecl = If->getConditionVariable()) { + const SourceRange &sourceRange = varDecl->getSourceRange(); - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, varDecl->getType(), DefaultRowMaj); + PushNextNodeId(Refl, SM, LangOpts, varDecl->getName(), varDecl, + D3D12_HLSL_NODE_TYPE_VARIABLE, ifNode, typeId, + &sourceRange, &FwdDecls); + } - const SourceRange &sourceRange = varDecl->getSourceRange(); + uint32_t start = uint32_t(Refl.Nodes.size()); - PushNextNodeId(Refl, SM, LangOpts, varDecl->getName(), varDecl, - D3D12_HLSL_NODE_TYPE_VARIABLE, ifNode, typeId, - &sourceRange, &FwdDecls); - } + RecursiveReflectBody(If->getThen(), ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, ifNode, + DefaultRowMaj, FwdDecls, LangOpts); - uint32_t start = uint32_t(Refl.Nodes.size()); + uint32_t thenCount = uint32_t(Refl.Nodes.size()) - start; - RecursiveReflectBody(If->getThen(), ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, ifNode, - DefaultRowMaj, FwdDecls, LangOpts); + RecursiveReflectBody(If->getElse(), ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, ifNode, + DefaultRowMaj, FwdDecls, LangOpts); - uint32_t thenCount = uint32_t(Refl.Nodes.size()) - start; + Refl.Ifs[ifLoc] = + DxcHLSLIf(ifNode, thenCount, If->getConditionVariable(), If->getElse()); + } - RecursiveReflectBody(If->getElse(), ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, ifNode, - DefaultRowMaj, FwdDecls, LangOpts); + else if (const ForStmt *For = dyn_cast(Statement)) { + // For->getInit(); + // For->getBody(); + } - Refl.Ifs[ifLoc] = DxcHLSLIf(ifNode, thenCount, If->getConditionVariable(), - If->getElse()); - } + else if (const WhileStmt *While = dyn_cast(Statement)) { + // While->getBody(); + // While->getCond(); + } - else if (const ForStmt *For = dyn_cast(subStmt)) { - // For->getInit(); - // For->getBody(); - } + else if (const DoStmt *Do = dyn_cast(Statement)) { + // Do->getBody(); + } - else if (const WhileStmt *While = dyn_cast(subStmt)) { - // While->getBody(); - // While->getCond(); - } + else if (const CompoundStmt *scope = dyn_cast(Statement)) { - else if (const DoStmt *Do = dyn_cast(subStmt)) { - // Do->getBody(); - } + const SourceRange &sourceRange = scope->getSourceRange(); - else if (const CompoundStmt *Scope = dyn_cast(subStmt)) { - // Scope->body(); - } + uint32_t scopeNode = PushNextNodeId( + Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_SCOPE, + ParentNodeId, 0, &sourceRange, &FwdDecls); - else if (const DeclStmt *DS = dyn_cast(subStmt)) { - for (Decl *D : DS->decls()) { - if (VarDecl *varDecl = llvm::dyn_cast(D)) { + for (const Stmt *child : scope->body()) + RecursiveReflectBody(child, ASTCtx, Diags, SM, Refl, AutoBindingSpace, + Depth + 1, Features, scopeNode, DefaultRowMaj, + FwdDecls, LangOpts); + } - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, varDecl->getType(), DefaultRowMaj); + else if (const DeclStmt *DS = dyn_cast(Statement)) { + for (Decl *D : DS->decls()) { + if (VarDecl *varDecl = dyn_cast(D)) { - const SourceRange &sourceRange = varDecl->getSourceRange(); + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, varDecl->getType(), DefaultRowMaj); - PushNextNodeId(Refl, SM, LangOpts, varDecl->getName(), varDecl, - D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId, - &sourceRange, &FwdDecls); - } + const SourceRange &sourceRange = varDecl->getSourceRange(); + + PushNextNodeId(Refl, SM, LangOpts, varDecl->getName(), varDecl, + D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId, + &sourceRange, &FwdDecls); } } } @@ -1380,8 +1382,9 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) continue; - - // TODO: Add Depth > 0 for reflection if D3D12_HLSL_REFLECTION_FEATURE_SCOPES + + // TODO: Add Depth > 0 for reflection if + // D3D12_HLSL_REFLECTION_FEATURE_SCOPES if (Depth != 0) continue; @@ -1390,19 +1393,18 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), CBuffer->getName(), CBuffer, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, uint32_t(Refl.Registers.size())); - + uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, SM, CBuffer, nodeId, D3D_CT_CBUFFER, DefaultRowMaj); - DxcHLSLRegister regD3D12 = { - D3D_SIT_CBUFFER, - 1, - uint32_t(D3D_SIF_USERPACKED), - D3D_RESOURCE_RETURN_TYPE(0), - D3D_SRV_DIMENSION_UNKNOWN, - nodeId, - uint32_t(-1), - bufferId}; + DxcHLSLRegister regD3D12 = {D3D_SIT_CBUFFER, + 1, + uint32_t(D3D_SIF_USERPACKED), + D3D_RESOURCE_RETURN_TYPE(0), + D3D_SRV_DIMENSION_UNKNOWN, + nodeId, + uint32_t(-1), + bufferId}; Refl.Registers.push_back(regD3D12); } @@ -1422,7 +1424,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, uint32_t(Refl.Functions.size()), nullptr, &FwdDecls); - if (nodeId == uint32_t(-1)) //Duplicate fwd definition + if (nodeId == uint32_t(-1)) // Duplicate fwd definition continue; bool hasDefinition = Func->hasBody(Definition); @@ -1432,20 +1434,28 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, for (uint32_t i = 0; i < func.GetNumParameters(); ++i) AddFunctionParameter(ASTCtx, Func->getParamDecl(i)->getType(), - Func->getParamDecl(i), Refl, SM, nodeId, - DefaultRowMaj); + Func->getParamDecl(i), Refl, SM, nodeId, + DefaultRowMaj); if (func.HasReturn()) AddFunctionParameter(ASTCtx, Func->getReturnType(), nullptr, Refl, SM, - nodeId, DefaultRowMaj); + nodeId, DefaultRowMaj); Refl.Functions.push_back(std::move(func)); if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { - clang::Stmt *stmt = Func->getBody(); - RecursiveReflectBody(stmt, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, nodeId, DefaultRowMaj, - FwdDecls, ASTCtx.getLangOpts()); + + Stmt *stmt = Func->getBody(); + + for (const Stmt *subStmt : stmt->children()) { + + if (!subStmt) + continue; + + RecursiveReflectBody(subStmt, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth, Features, nodeId, + DefaultRowMaj, FwdDecls, ASTCtx.getLangOpts()); + } } } @@ -1731,7 +1741,7 @@ static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { static const char *arr[] = { "Register", "Function", "Enum", "EnumValue", "Namespace", "Variable", "Typedef", "Struct", "Union", "StaticVariable", - "Interface", "Parameter", "If"}; + "Interface", "Parameter", "If", "Scope"}; return arr[uint32_t(type)]; } @@ -2013,11 +2023,15 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, const DxcHLSLIf &If = Refl.Ifs[localId]; const DxcHLSLNode &Node = Refl.Nodes[If.NodeId]; - printf("%sif nodes: %u, else nodes: %u%s%s\n", - std::string(Depth, '\t').c_str(), If.GetIfNodes(), - Node.GetChildCount() - If.GetIfNodes() - If.HasConditionVar(), - If.HasConditionVar() ? " (has cond var)" : "", - If.HasElse() ? " (has else)" : ""); + uint32_t elseNodes = + Node.GetChildCount() - If.GetIfNodes() - If.HasConditionVar(); + + if (elseNodes || If.GetIfNodes() || If.HasConditionVar() || + If.HasElse()) + printf("%sif nodes: %u, else nodes: %u%s%s\n", + std::string(Depth, '\t').c_str(), If.GetIfNodes(), elseNodes, + If.HasConditionVar() ? " (has cond var)" : "", + If.HasElse() ? " (has else)" : ""); break; } @@ -2051,6 +2065,7 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, } case D3D12_HLSL_NODE_TYPE_NAMESPACE: + case D3D12_HLSL_NODE_TYPE_SCOPE: default: break; } @@ -2426,6 +2441,8 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if(Sources[i] >= header.Strings) throw std::invalid_argument("Source path out of bounds"); + std::vector validateChildren; + for (uint32_t i = 0; i < header.Nodes; ++i) { const DxcHLSLNode &node = Nodes[i]; @@ -2474,10 +2491,10 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION) - throw std::invalid_argument( - "Node " + std::to_string(i) + - " is a parameter but parent isn't a function"); - + throw std::invalid_argument( + "Node " + std::to_string(i) + + " is a parameter but parent isn't a function"); + break; case D3D12_HLSL_NODE_TYPE_IF: @@ -2486,7 +2503,8 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION && - Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_IF) + Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_IF && + Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_SCOPE) throw std::invalid_argument( "Node " + std::to_string(i) + " is an if but parent isn't a function or if"); @@ -2506,6 +2524,9 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes allowFwdDeclare = true; maxValue = node.IsFwdDeclare() ? 1 : header.Types; break; + + case D3D12_HLSL_NODE_TYPE_SCOPE: + break; } switch (node.GetNodeType()) { @@ -2515,9 +2536,14 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: case D3D12_HLSL_NODE_TYPE_PARAMETER: if (node.GetChildCount()) - throw std::invalid_argument("Node " + std::to_string(i) + - " is a parameter, typedef, variable or " - "static variable but also has children"); + throw std::invalid_argument("Node " + std::to_string(i) + + " is a parameter, typedef, variable or " + "static variable but also has children"); + + case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_SCOPE: + if (node.GetChildCount()) + validateChildren.push_back(i); } if ((node.GetNodeType() == D3D12_HLSL_NODE_TYPE_REGISTER || @@ -2714,6 +2740,37 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes " has invalid data"); } + for (uint32_t nodeId : validateChildren) { + + const DxcHLSLNode &node = Nodes[nodeId]; + + // If/Then/Scope children could only be + // struct/union/interface/if/variable/typedef/enum + + for (uint32_t j = 0; j < node.GetChildCount(); ++j) { + + const DxcHLSLNode &childNode = Nodes[nodeId + 1 + j]; + + switch (childNode.GetNodeType()) { + case D3D12_HLSL_NODE_TYPE_VARIABLE: + case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_STRUCT: + case D3D12_HLSL_NODE_TYPE_UNION: + case D3D12_HLSL_NODE_TYPE_INTERFACE: + case D3D12_HLSL_NODE_TYPE_TYPEDEF: + case D3D12_HLSL_NODE_TYPE_ENUM: + case D3D12_HLSL_NODE_TYPE_SCOPE: + break; + default: + throw std::invalid_argument( + "Node " + std::to_string(nodeId) + + " has if/then/scope with children of invalid type"); + } + + j += childNode.GetChildCount(); + } + } + for (uint32_t i = 0; i < header.Ifs; ++i) { const DxcHLSLIf &If = Ifs[i]; @@ -2737,31 +2794,6 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes throw std::invalid_argument( "If " + std::to_string(i) + " has condition variable but first child is not a variable"); - - // If/Then children could only be - // struct/union/interface/if/variable/typedef/enum (We skip condition var) - - for (uint32_t j = ifCondVar; j < node.GetChildCount(); ++j) { - - const DxcHLSLNode &childNode = Nodes[If.NodeId + 1 + j]; - - switch (childNode.GetNodeType()) { - case D3D12_HLSL_NODE_TYPE_VARIABLE: - case D3D12_HLSL_NODE_TYPE_IF: - case D3D12_HLSL_NODE_TYPE_STRUCT: - case D3D12_HLSL_NODE_TYPE_UNION: - case D3D12_HLSL_NODE_TYPE_INTERFACE: - case D3D12_HLSL_NODE_TYPE_TYPEDEF: - case D3D12_HLSL_NODE_TYPE_ENUM: - break; - default: - throw std::invalid_argument( - "If " + std::to_string(i) + - " has if/then with children of invalid type"); - } - - j += childNode.GetChildCount(); - } } for (uint32_t i = 0; i < header.Types; ++i) { From 83b33216f79351177df36acf27f2e828e0591119 Mon Sep 17 00:00:00 2001 From: NielsbishereAlt Date: Mon, 13 Oct 2025 06:43:32 +0200 Subject: [PATCH 056/126] Now fixed every if/else introducing unncessary scopes --- tools/clang/tools/dxcreflection/DxcReflection.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 189654eeb3..87e39426c4 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1256,7 +1256,8 @@ static void RecursiveReflectBody( uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls, - const LangOptions &LangOpts) { + const LangOptions &LangOpts, + bool SkipNextCompound = false) { if (!Statement) return; @@ -1288,13 +1289,15 @@ static void RecursiveReflectBody( RecursiveReflectBody(If->getThen(), ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, ifNode, - DefaultRowMaj, FwdDecls, LangOpts); + DefaultRowMaj, FwdDecls, LangOpts, + If->getThen() && dyn_cast(If->getThen())); uint32_t thenCount = uint32_t(Refl.Nodes.size()) - start; RecursiveReflectBody(If->getElse(), ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, ifNode, - DefaultRowMaj, FwdDecls, LangOpts); + DefaultRowMaj, FwdDecls, LangOpts, + If->getElse() && dyn_cast(If->getElse())); Refl.Ifs[ifLoc] = DxcHLSLIf(ifNode, thenCount, If->getConditionVariable(), If->getElse()); @@ -1318,7 +1321,7 @@ static void RecursiveReflectBody( const SourceRange &sourceRange = scope->getSourceRange(); - uint32_t scopeNode = PushNextNodeId( + uint32_t scopeNode = SkipNextCompound ? ParentNodeId : PushNextNodeId( Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_SCOPE, ParentNodeId, 0, &sourceRange, &FwdDecls); From 9195605e90a760a98ebe9b87459760506acf3593 Mon Sep 17 00:00:00 2001 From: NielsbishereAlt Date: Mon, 13 Oct 2025 06:50:40 +0200 Subject: [PATCH 057/126] Added do --- include/dxc/dxctools.h | 4 +-- .../tools/dxcreflection/DxcReflection.cpp | 36 +++++++++++++------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 57aa606525..f393ff428c 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -189,9 +189,9 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_IF, D3D12_HLSL_NODE_TYPE_SCOPE, + D3D12_HLSL_NODE_TYPE_DO, // D3D12_HLSL_NODE_TYPE_FOR, // D3D12_HLSL_NODE_TYPE_SWITCH, - // D3D12_HLSL_NODE_TYPE_DO, // TODO: D3D12_HLSL_NODE_TYPE_USING, @@ -201,7 +201,7 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, // Don't forget to properly update NodeTypeToString - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_SCOPE + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_DO }; struct D3D12_HLSL_NODE { diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 87e39426c4..bba7a93576 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1287,17 +1287,17 @@ static void RecursiveReflectBody( uint32_t start = uint32_t(Refl.Nodes.size()); - RecursiveReflectBody(If->getThen(), ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, ifNode, - DefaultRowMaj, FwdDecls, LangOpts, - If->getThen() && dyn_cast(If->getThen())); + RecursiveReflectBody( + If->getThen(), ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, ifNode, DefaultRowMaj, FwdDecls, LangOpts, + If->getThen() && dyn_cast(If->getThen())); uint32_t thenCount = uint32_t(Refl.Nodes.size()) - start; - RecursiveReflectBody(If->getElse(), ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, ifNode, - DefaultRowMaj, FwdDecls, LangOpts, - If->getElse() && dyn_cast(If->getElse())); + RecursiveReflectBody( + If->getElse(), ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, ifNode, DefaultRowMaj, FwdDecls, LangOpts, + If->getElse() && dyn_cast(If->getElse())); Refl.Ifs[ifLoc] = DxcHLSLIf(ifNode, thenCount, If->getConditionVariable(), If->getElse()); @@ -1314,7 +1314,16 @@ static void RecursiveReflectBody( } else if (const DoStmt *Do = dyn_cast(Statement)) { - // Do->getBody(); + + const SourceRange &sourceRange = Do->getSourceRange(); + + uint32_t scopeNode = + PushNextNodeId(Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_DO, + ParentNodeId, 0, &sourceRange, &FwdDecls); + + RecursiveReflectBody(Do->getBody(), ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, scopeNode, + DefaultRowMaj, FwdDecls, LangOpts, true); } else if (const CompoundStmt *scope = dyn_cast(Statement)) { @@ -1744,7 +1753,7 @@ static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { static const char *arr[] = { "Register", "Function", "Enum", "EnumValue", "Namespace", "Variable", "Typedef", "Struct", "Union", "StaticVariable", - "Interface", "Parameter", "If", "Scope"}; + "Interface", "Parameter", "If", "Scope", "Do"}; return arr[uint32_t(type)]; } @@ -2069,6 +2078,7 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, case D3D12_HLSL_NODE_TYPE_NAMESPACE: case D3D12_HLSL_NODE_TYPE_SCOPE: + case D3D12_HLSL_NODE_TYPE_DO: default: break; } @@ -2507,7 +2517,8 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION && Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_IF && - Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_SCOPE) + Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_SCOPE && + Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_DO) throw std::invalid_argument( "Node " + std::to_string(i) + " is an if but parent isn't a function or if"); @@ -2529,6 +2540,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes break; case D3D12_HLSL_NODE_TYPE_SCOPE: + case D3D12_HLSL_NODE_TYPE_DO: break; } @@ -2545,6 +2557,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_IF: case D3D12_HLSL_NODE_TYPE_SCOPE: + case D3D12_HLSL_NODE_TYPE_DO: if (node.GetChildCount()) validateChildren.push_back(i); } @@ -2763,6 +2776,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_ENUM: case D3D12_HLSL_NODE_TYPE_SCOPE: + case D3D12_HLSL_NODE_TYPE_DO: break; default: throw std::invalid_argument( From d6305af5f87986c6398252fc446beaba56cc2822 Mon Sep 17 00:00:00 2001 From: NielsbishereAlt Date: Mon, 13 Oct 2025 11:10:12 +0200 Subject: [PATCH 058/126] Added DxcHLSLForWhileSwitch temporarily, though likely it'll change to WhileSwitch since For has condition variable and init variables. Strengthened some validation. --- include/dxc/DxcReflection/DxcReflection.h | 35 +++- include/dxc/dxctools.h | 5 +- .../tools/dxcreflection/DxcReflection.cpp | 194 ++++++++++++++---- 3 files changed, 183 insertions(+), 51 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 90743d8eac..e2718dd722 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -308,9 +308,34 @@ struct DxcHLSLIf { bool HasElse() const { return (HasConditionVar_HasElse_IfNodes >> 31) & 1; } - bool operator==(const DxcHLSLIf &other) const { - return NodeId == other.NodeId && HasConditionVar_HasElse_IfNodes == - other.HasConditionVar_HasElse_IfNodes; + bool operator==(const DxcHLSLIf &Other) const { + return NodeId == Other.NodeId && HasConditionVar_HasElse_IfNodes == + Other.HasConditionVar_HasElse_IfNodes; + } +}; + +struct DxcHLSLForWhileSwitch { + + enum Type { For, While, Switch, Count, Start = For }; + + uint32_t NodeId; + uint32_t Type_HasConditionVar; + + DxcHLSLForWhileSwitch() = default; + + DxcHLSLForWhileSwitch(uint32_t NodeId, Type T, bool HasConditionVar) + : NodeId(NodeId), + Type_HasConditionVar(uint32_t(T) | (HasConditionVar ? (1u << 31) : 0)) { + if (T >= Type::Count || T < Type::Start) + throw std::invalid_argument("Type out of bounds"); + } + + Type GetType() const { return Type(Type_HasConditionVar << 1 >> 1); } + bool HasConditionVar() const { return (Type_HasConditionVar >> 31) & 1; } + + bool operator==(const DxcHLSLForWhileSwitch &Other) const { + return NodeId == Other.NodeId && + Type_HasConditionVar == Other.Type_HasConditionVar; } }; @@ -586,6 +611,7 @@ struct DxcHLSLReflectionData { std::vector Buffers; std::vector Ifs; + std::vector ForWhileSwitches; // Can be stripped if !(D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) @@ -623,7 +649,8 @@ struct DxcHLSLReflectionData { ArraySizes == Other.ArraySizes && MemberTypeIds == Other.MemberTypeIds && TypeList == Other.TypeList && Types == Other.Types && Buffers == Other.Buffers && - Parameters == Other.Parameters && Ifs == Other.Ifs; + Parameters == Other.Parameters && Ifs == Other.Ifs && + ForWhileSwitches == Other.ForWhileSwitches; } bool operator==(const DxcHLSLReflectionData &Other) const { diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index f393ff428c..9f6b1cc0a6 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -190,8 +190,7 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_IF, D3D12_HLSL_NODE_TYPE_SCOPE, D3D12_HLSL_NODE_TYPE_DO, - // D3D12_HLSL_NODE_TYPE_FOR, - // D3D12_HLSL_NODE_TYPE_SWITCH, + D3D12_HLSL_NODE_TYPE_FORWHILESWITCH, // TODO: D3D12_HLSL_NODE_TYPE_USING, @@ -201,7 +200,7 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, // Don't forget to properly update NodeTypeToString - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_DO + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_FORWHILESWITCH }; struct D3D12_HLSL_NODE { diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index bba7a93576..38b21324e6 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -71,9 +71,11 @@ static uint32_t RegisterString(DxcHLSLReflectionData &Refl, static uint32_t PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, const LangOptions &LangOpts, const std::string &UnqualifiedName, - Decl *DeclSelf, D3D12_HLSL_NODE_TYPE Type, uint32_t ParentNodeId, - uint32_t LocalId, const SourceRange *Range = nullptr, - std::unordered_map *FwdDecls = nullptr) { + const Decl *DeclSelf, D3D12_HLSL_NODE_TYPE Type, + uint32_t ParentNodeId, uint32_t LocalId, + const SourceRange *Range = nullptr, + std::unordered_map *FwdDecls = nullptr) +{ if (Refl.Nodes.size() >= (1u << 24)) throw std::invalid_argument("Nodes overflow"); @@ -123,7 +125,7 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, } } - if (ValueDecl *valDecl = dyn_cast(DeclSelf)) { + if (const ValueDecl *valDecl = dyn_cast(DeclSelf)) { const ArrayRef &UA = valDecl->getUnusualAnnotations(); @@ -138,23 +140,23 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, bool isFwdDeclare = false; bool canHaveFwdDeclare = false; - Decl *fwdDeclare = nullptr; + const Decl *fwdDeclare = nullptr; if (DeclSelf) { - if (FunctionDecl *func = dyn_cast(DeclSelf)) { + if (const FunctionDecl *func = dyn_cast(DeclSelf)) { isFwdDeclare = !func->doesThisDeclarationHaveABody(); fwdDeclare = func->getCanonicalDecl(); canHaveFwdDeclare = true; } - else if (EnumDecl *enm = dyn_cast(DeclSelf)) { + else if (const EnumDecl *enm = dyn_cast(DeclSelf)) { isFwdDeclare = !enm->isCompleteDefinition(); fwdDeclare = enm->getCanonicalDecl(); canHaveFwdDeclare = true; } - else if (RecordDecl *rec = dyn_cast(DeclSelf)) { + else if (const RecordDecl *rec = dyn_cast(DeclSelf)) { isFwdDeclare = !rec->isThisDeclarationADefinition(); fwdDeclare = rec->getCanonicalDecl(); @@ -1255,9 +1257,52 @@ static void RecursiveReflectBody( const SourceManager &SM, DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, - bool DefaultRowMaj, std::unordered_map &FwdDecls, + bool DefaultRowMaj, std::unordered_map &FwdDecls, + const LangOptions &LangOpts, bool SkipNextCompound = false); + +static void GenerateForWhileSwitch( + ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, + DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, + D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, + bool DefaultRowMaj, std::unordered_map &FwdDecls, + const LangOptions &LangOpts, DxcHLSLForWhileSwitch::Type Type, + const VarDecl *VarDecl, const Stmt *Body, const Stmt *Self) { + + uint32_t loc = uint32_t(Refl.ForWhileSwitches.size()); + + const SourceRange &sourceRange = Self->getSourceRange(); + + uint32_t nodeId = PushNextNodeId(Refl, SM, LangOpts, "", nullptr, + D3D12_HLSL_NODE_TYPE_FORWHILESWITCH, + ParentNodeId, loc, &sourceRange, &FwdDecls); + + Refl.ForWhileSwitches.push_back(DxcHLSLForWhileSwitch(nodeId, Type, VarDecl)); + + if (VarDecl) { + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, VarDecl->getType(), DefaultRowMaj); + + const SourceRange &sourceRange = VarDecl->getSourceRange(); + + PushNextNodeId(Refl, SM, LangOpts, VarDecl->getName(), VarDecl, + D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, typeId, &sourceRange, + &FwdDecls); + } + + RecursiveReflectBody(Body, ASTCtx, Diags, SM, Refl, AutoBindingSpace, + Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls, + LangOpts, true); +} + +static void RecursiveReflectBody( + const Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, + const SourceManager &SM, DxcHLSLReflectionData &Refl, + uint32_t AutoBindingSpace, uint32_t Depth, + D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, + bool DefaultRowMaj, std::unordered_map &FwdDecls, const LangOptions &LangOpts, - bool SkipNextCompound = false) { + bool SkipNextCompound) { if (!Statement) return; @@ -1287,31 +1332,39 @@ static void RecursiveReflectBody( uint32_t start = uint32_t(Refl.Nodes.size()); - RecursiveReflectBody( - If->getThen(), ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ifNode, DefaultRowMaj, FwdDecls, LangOpts, - If->getThen() && dyn_cast(If->getThen())); + RecursiveReflectBody(If->getThen(), ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, ifNode, + DefaultRowMaj, FwdDecls, LangOpts, true); uint32_t thenCount = uint32_t(Refl.Nodes.size()) - start; - RecursiveReflectBody( - If->getElse(), ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ifNode, DefaultRowMaj, FwdDecls, LangOpts, - If->getElse() && dyn_cast(If->getElse())); + RecursiveReflectBody(If->getElse(), ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, ifNode, + DefaultRowMaj, FwdDecls, LangOpts, true); Refl.Ifs[ifLoc] = DxcHLSLIf(ifNode, thenCount, If->getConditionVariable(), If->getElse()); } - else if (const ForStmt *For = dyn_cast(Statement)) { - // For->getInit(); - // For->getBody(); - } + else if (const ForStmt *For = dyn_cast(Statement)) + GenerateForWhileSwitch(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, ParentNodeId, DefaultRowMaj, FwdDecls, + LangOpts, DxcHLSLForWhileSwitch::For, + For->getConditionVariable(), For->getBody(), For); - else if (const WhileStmt *While = dyn_cast(Statement)) { - // While->getBody(); - // While->getCond(); - } + else if (const WhileStmt *While = dyn_cast(Statement)) + GenerateForWhileSwitch(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, ParentNodeId, DefaultRowMaj, FwdDecls, + LangOpts, DxcHLSLForWhileSwitch::While, + While->getConditionVariable(), While->getBody(), + While); + + else if (const SwitchStmt *Switch = dyn_cast(Statement)) + GenerateForWhileSwitch(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, ParentNodeId, DefaultRowMaj, FwdDecls, + LangOpts, DxcHLSLForWhileSwitch::Switch, + Switch->getConditionVariable(), Switch->getBody(), + Switch); else if (const DoStmt *Do = dyn_cast(Statement)) { @@ -1363,7 +1416,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, - std::unordered_map &FwdDecls) { + std::unordered_map &FwdDecls) { PrintfStream pfStream; @@ -1709,7 +1762,7 @@ bool DxcHLSLReflectionData::Initialize(clang::CompilerInstance &Compiler, try { - std::unordered_map fwdDecls; + std::unordered_map fwdDecls; RecursiveReflectHLSL(Ctx, Compiler.getASTContext(), Diags, SM, Result, AutoBindingSpace, 0, Features, 0, DefaultRowMaj, fwdDecls); @@ -1751,9 +1804,10 @@ static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { static const char *arr[] = { - "Register", "Function", "Enum", "EnumValue", "Namespace", - "Variable", "Typedef", "Struct", "Union", "StaticVariable", - "Interface", "Parameter", "If", "Scope", "Do"}; + "Register", "Function", "Enum", "EnumValue", + "Namespace", "Variable", "Typedef", "Struct", + "Union", "StaticVariable", "Interface", "Parameter", + "If", "Scope", "Do", "ForWhileSwitch"}; return arr[uint32_t(type)]; } @@ -2048,6 +2102,19 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, break; } + case D3D12_HLSL_NODE_TYPE_FORWHILESWITCH: { + + const DxcHLSLForWhileSwitch &ForWhileSwitch = + Refl.ForWhileSwitches[localId]; + + static const char *types[] = {"For", "While", "Switch"}; + + printf("%s%s\n", std::string(Depth, '\t').c_str(), + types[ForWhileSwitch.GetType()]); + + break; + } + case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: @@ -2127,7 +2194,7 @@ struct DxcHLSLHeader { uint32_t Parameters; uint32_t Ifs; - uint32_t Pad; + uint32_t ForWhileSwitches; }; template @@ -2385,7 +2452,8 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, - Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, TypeNameIds, Buffers, Parameters, Ifs); + Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, TypeNameIds, + Buffers, Parameters, Ifs, ForWhileSwitches); Bytes.resize(toReserve); @@ -2401,14 +2469,15 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { uint32_t(Arrays.size()), uint32_t(ArraySizes.size()), uint32_t(MemberTypeIds.size()), uint32_t(Types.size()), uint32_t(Buffers.size()), uint32_t(TypeList.size()), - uint32_t(Parameters.size()), uint32_t(Ifs.size())}; + uint32_t(Parameters.size()), uint32_t(Ifs.size()), + uint32_t(ForWhileSwitches.size())}; toReserve += sizeof(DxcHLSLHeader); Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, - TypeNameIds, Buffers, Parameters, Ifs); + TypeNameIds, Buffers, Parameters, Ifs, ForWhileSwitches); } DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes, @@ -2443,7 +2512,8 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes Arrays, header.Arrays, MemberTypeIds, header.Members, TypeList, header.TypeListCount, MemberNameIds, memberSymbolCount, Types, header.Types, TypeNameIds, typeSymbolCount, Buffers, header.Buffers, - Parameters, header.Parameters, Ifs, header.Ifs); + Parameters, header.Parameters, Ifs, header.Ifs, ForWhileSwitches, + header.ForWhileSwitches); // Validation errors are throws to prevent accessing invalid data @@ -2511,17 +2581,29 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes break; case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_SCOPE: + case D3D12_HLSL_NODE_TYPE_DO: + case D3D12_HLSL_NODE_TYPE_FORWHILESWITCH: - maxValue = header.Ifs; + maxValue = + node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF + ? header.Ifs + : (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_FORWHILESWITCH + ? header.ForWhileSwitches + : 1); if (Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION && Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_IF && - Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_SCOPE && - Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_DO) + Nodes[node.GetParentId()].GetNodeType() != + D3D12_HLSL_NODE_TYPE_SCOPE && + Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_DO && + Nodes[node.GetParentId()].GetNodeType() != + D3D12_HLSL_NODE_TYPE_FORWHILESWITCH) throw std::invalid_argument( "Node " + std::to_string(i) + - " is an if but parent isn't a function or if"); + " is an if/scope/do/for/while/switch but parent isn't of a similar " + "type or function"); break; @@ -2538,10 +2620,6 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes allowFwdDeclare = true; maxValue = node.IsFwdDeclare() ? 1 : header.Types; break; - - case D3D12_HLSL_NODE_TYPE_SCOPE: - case D3D12_HLSL_NODE_TYPE_DO: - break; } switch (node.GetNodeType()) { @@ -2558,6 +2636,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_IF: case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: + case D3D12_HLSL_NODE_TYPE_FORWHILESWITCH: if (node.GetChildCount()) validateChildren.push_back(i); } @@ -2777,6 +2856,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_ENUM: case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: + case D3D12_HLSL_NODE_TYPE_FORWHILESWITCH: break; default: throw std::invalid_argument( @@ -2812,6 +2892,32 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes "If " + std::to_string(i) + " has condition variable but first child is not a variable"); } + + for (uint32_t i = 0; i < header.ForWhileSwitches; ++i) { + + const DxcHLSLForWhileSwitch &ForWhileSwitch = ForWhileSwitches[i]; + + if (ForWhileSwitch.NodeId >= header.Nodes || + Nodes[ForWhileSwitch.NodeId].GetNodeType() != + D3D12_HLSL_NODE_TYPE_FORWHILESWITCH || + Nodes[ForWhileSwitch.NodeId].GetLocalId() != i) + throw std::invalid_argument("ForWhileSwitch " + std::to_string(i) + + " points to an invalid nodeId"); + + bool ifCondVar = ForWhileSwitch.HasConditionVar(); + uint32_t minParamCount = ifCondVar; + const DxcHLSLNode &node = Nodes[ForWhileSwitch.NodeId]; + + if (node.GetChildCount() < minParamCount) + throw std::invalid_argument("ForWhileSwitch " + std::to_string(i) + + " didn't have required child nodes"); + + if (ifCondVar && Nodes[ForWhileSwitch.NodeId + 1].GetNodeType() != + D3D12_HLSL_NODE_TYPE_VARIABLE) + throw std::invalid_argument( + "ForWhileSwitch " + std::to_string(i) + + " has condition variable but first child is not a variable"); + } for (uint32_t i = 0; i < header.Types; ++i) { From e23146b07abdab582b0fe8e619425138588466d8 Mon Sep 17 00:00:00 2001 From: NielsbishereAlt Date: Tue, 14 Oct 2025 11:20:20 +0200 Subject: [PATCH 059/126] Unified if/switch/while/for into DxcHLSLStatement. This can handle conditional variables and node count (if: then body, for: init) and the leftover of the body is just the body (or the else in the case of if). Cleaned up some code. --- include/dxc/DxcReflection/DxcReflection.h | 74 ++---- include/dxc/dxctools.h | 9 +- .../tools/dxcreflection/DxcReflection.cpp | 251 ++++++++---------- 3 files changed, 143 insertions(+), 191 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index e2718dd722..9941c7868d 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -281,61 +281,45 @@ struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC without duplicating } }; -struct DxcHLSLIf { +// A statement is a for, while, if, switch. Basically every Stmt except do or scope. +// It can contain the following child nodes: +// - if HasConditionVar(): a variable in the condition +// - NodeCount children (If: children ex. else body, For: init children) +// - Rest of the body (If: else body, otherwise: normal body) +struct DxcHLSLStatement { uint32_t NodeId; - uint32_t HasConditionVar_HasElse_IfNodes; + uint32_t NodeCount_HasConditionVar_HasElse; - DxcHLSLIf() = default; + DxcHLSLStatement() = default; - DxcHLSLIf(uint32_t NodeId, uint32_t IfNodes, bool HasConditionVar, - bool HasElse) + DxcHLSLStatement(uint32_t NodeId, uint32_t NodeCount, bool HasConditionVar, + bool IfAndHasElse) : NodeId(NodeId), - HasConditionVar_HasElse_IfNodes(IfNodes | - (HasConditionVar ? (1u << 30) : 0) | - (HasElse ? (1u << 31) : 0)) { - if (IfNodes >= (1u << 30)) - throw std::invalid_argument("IfNodes out of bounds"); + NodeCount_HasConditionVar_HasElse(NodeCount | + (HasConditionVar ? (1u << 30) : 0) | + (IfAndHasElse ? (1u << 31) : 0)) { + if (NodeCount >= (1u << 30)) + throw std::invalid_argument("NodeCount out of bounds"); } - uint32_t GetIfNodes() const { - return HasConditionVar_HasElse_IfNodes << 2 >> 2; + // Node count represents one of two things: + // - If: The amount of nodes in the 'if' part of the branch (to be able to + // find the else part) + // - For: The amount of nodes in the initialize part of the for + uint32_t GetNodeCount() const { + return NodeCount_HasConditionVar_HasElse << 2 >> 2; } bool HasConditionVar() const { - return (HasConditionVar_HasElse_IfNodes >> 30) & 1; + return (NodeCount_HasConditionVar_HasElse >> 30) & 1; } + bool HasElse() const { return (NodeCount_HasConditionVar_HasElse >> 31) & 1; } - bool HasElse() const { return (HasConditionVar_HasElse_IfNodes >> 31) & 1; } - - bool operator==(const DxcHLSLIf &Other) const { - return NodeId == Other.NodeId && HasConditionVar_HasElse_IfNodes == - Other.HasConditionVar_HasElse_IfNodes; - } -}; - -struct DxcHLSLForWhileSwitch { - - enum Type { For, While, Switch, Count, Start = For }; - - uint32_t NodeId; - uint32_t Type_HasConditionVar; - - DxcHLSLForWhileSwitch() = default; - - DxcHLSLForWhileSwitch(uint32_t NodeId, Type T, bool HasConditionVar) - : NodeId(NodeId), - Type_HasConditionVar(uint32_t(T) | (HasConditionVar ? (1u << 31) : 0)) { - if (T >= Type::Count || T < Type::Start) - throw std::invalid_argument("Type out of bounds"); - } - - Type GetType() const { return Type(Type_HasConditionVar << 1 >> 1); } - bool HasConditionVar() const { return (Type_HasConditionVar >> 31) & 1; } - - bool operator==(const DxcHLSLForWhileSwitch &Other) const { + bool operator==(const DxcHLSLStatement &Other) const { return NodeId == Other.NodeId && - Type_HasConditionVar == Other.Type_HasConditionVar; + NodeCount_HasConditionVar_HasElse == + Other.NodeCount_HasConditionVar_HasElse; } }; @@ -610,8 +594,7 @@ struct DxcHLSLReflectionData { std::vector Types; std::vector Buffers; - std::vector Ifs; - std::vector ForWhileSwitches; + std::vector Statements; // Can be stripped if !(D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) @@ -649,8 +632,7 @@ struct DxcHLSLReflectionData { ArraySizes == Other.ArraySizes && MemberTypeIds == Other.MemberTypeIds && TypeList == Other.TypeList && Types == Other.Types && Buffers == Other.Buffers && - Parameters == Other.Parameters && Ifs == Other.Ifs && - ForWhileSwitches == Other.ForWhileSwitches; + Parameters == Other.Parameters && Statements == Other.Statements; } bool operator==(const DxcHLSLReflectionData &Other) const { diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 9f6b1cc0a6..646f962688 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -185,12 +185,15 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_INTERFACE, D3D12_HLSL_NODE_TYPE_PARAMETER, - // Control flow, for full inspection of what variables exist where and scopes + // Control flow (Stmts), for full inspection of what variables exist where and + // scopes D3D12_HLSL_NODE_TYPE_IF, D3D12_HLSL_NODE_TYPE_SCOPE, D3D12_HLSL_NODE_TYPE_DO, - D3D12_HLSL_NODE_TYPE_FORWHILESWITCH, + D3D12_HLSL_NODE_TYPE_SWITCH, + D3D12_HLSL_NODE_TYPE_WHILE, + D3D12_HLSL_NODE_TYPE_FOR, // TODO: D3D12_HLSL_NODE_TYPE_USING, @@ -200,7 +203,7 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, // Don't forget to properly update NodeTypeToString - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_FORWHILESWITCH + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_FOR }; struct D3D12_HLSL_NODE { diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 38b21324e6..9327f63765 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1260,23 +1260,23 @@ static void RecursiveReflectBody( bool DefaultRowMaj, std::unordered_map &FwdDecls, const LangOptions &LangOpts, bool SkipNextCompound = false); -static void GenerateForWhileSwitch( +static void GenerateStatement( ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls, - const LangOptions &LangOpts, DxcHLSLForWhileSwitch::Type Type, - const VarDecl *VarDecl, const Stmt *Body, const Stmt *Self) { + const LangOptions &LangOpts, D3D12_HLSL_NODE_TYPE Type, + const VarDecl *VarDecl, const Stmt *Body, const Stmt *Init, + const Stmt *Self, bool IfAndHasElse = false) { - uint32_t loc = uint32_t(Refl.ForWhileSwitches.size()); + uint32_t loc = uint32_t(Refl.Statements.size()); const SourceRange &sourceRange = Self->getSourceRange(); - uint32_t nodeId = PushNextNodeId(Refl, SM, LangOpts, "", nullptr, - D3D12_HLSL_NODE_TYPE_FORWHILESWITCH, + uint32_t nodeId = PushNextNodeId(Refl, SM, LangOpts, "", nullptr, Type, ParentNodeId, loc, &sourceRange, &FwdDecls); - Refl.ForWhileSwitches.push_back(DxcHLSLForWhileSwitch(nodeId, Type, VarDecl)); + Refl.Statements.push_back(DxcHLSLStatement()); if (VarDecl) { @@ -1290,6 +1290,15 @@ static void GenerateForWhileSwitch( &FwdDecls); } + uint32_t start = uint32_t(Refl.Nodes.size()); + + RecursiveReflectBody(Init, ASTCtx, Diags, SM, Refl, AutoBindingSpace, + Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls, + LangOpts, true); + + Refl.Statements[loc] = + DxcHLSLStatement(nodeId, uint32_t(Refl.Nodes.size() - start), VarDecl, IfAndHasElse); + RecursiveReflectBody(Body, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls, LangOpts, true); @@ -1307,63 +1316,31 @@ static void RecursiveReflectBody( if (!Statement) return; - if (const IfStmt *If = dyn_cast(Statement)) { - - uint32_t ifLoc = uint32_t(Refl.Ifs.size()); - Refl.Ifs.push_back(DxcHLSLIf()); - - const SourceRange &sourceRange = If->getSourceRange(); - - uint32_t ifNode = - PushNextNodeId(Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_IF, - ParentNodeId, ifLoc, &sourceRange, &FwdDecls); - - if (VarDecl *varDecl = If->getConditionVariable()) { - - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, varDecl->getType(), DefaultRowMaj); - - const SourceRange &sourceRange = varDecl->getSourceRange(); - - PushNextNodeId(Refl, SM, LangOpts, varDecl->getName(), varDecl, - D3D12_HLSL_NODE_TYPE_VARIABLE, ifNode, typeId, - &sourceRange, &FwdDecls); - } - - uint32_t start = uint32_t(Refl.Nodes.size()); - - RecursiveReflectBody(If->getThen(), ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, ifNode, - DefaultRowMaj, FwdDecls, LangOpts, true); - - uint32_t thenCount = uint32_t(Refl.Nodes.size()) - start; - - RecursiveReflectBody(If->getElse(), ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, ifNode, - DefaultRowMaj, FwdDecls, LangOpts, true); - - Refl.Ifs[ifLoc] = - DxcHLSLIf(ifNode, thenCount, If->getConditionVariable(), If->getElse()); - } + if (const IfStmt *If = dyn_cast(Statement)) + GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, + D3D12_HLSL_NODE_TYPE_IF, If->getConditionVariable(), + If->getElse(), If->getThen(), If, If->getElse()); else if (const ForStmt *For = dyn_cast(Statement)) - GenerateForWhileSwitch(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, ParentNodeId, DefaultRowMaj, FwdDecls, - LangOpts, DxcHLSLForWhileSwitch::For, - For->getConditionVariable(), For->getBody(), For); + LangOpts, D3D12_HLSL_NODE_TYPE_FOR, + For->getConditionVariable(), For->getBody(), + For->getInit(), For); else if (const WhileStmt *While = dyn_cast(Statement)) - GenerateForWhileSwitch(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, ParentNodeId, DefaultRowMaj, FwdDecls, - LangOpts, DxcHLSLForWhileSwitch::While, + LangOpts, D3D12_HLSL_NODE_TYPE_WHILE, While->getConditionVariable(), While->getBody(), - While); + nullptr, While); else if (const SwitchStmt *Switch = dyn_cast(Statement)) - GenerateForWhileSwitch(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, ParentNodeId, DefaultRowMaj, FwdDecls, - LangOpts, DxcHLSLForWhileSwitch::Switch, - Switch->getConditionVariable(), Switch->getBody(), + LangOpts, D3D12_HLSL_NODE_TYPE_SWITCH, + Switch->getConditionVariable(), Switch->getBody(), nullptr, Switch); else if (const DoStmt *Do = dyn_cast(Statement)) { @@ -1804,10 +1781,10 @@ static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { static const char *arr[] = { - "Register", "Function", "Enum", "EnumValue", - "Namespace", "Variable", "Typedef", "Struct", - "Union", "StaticVariable", "Interface", "Parameter", - "If", "Scope", "Do", "ForWhileSwitch"}; + "Register", "Function", "Enum", "EnumValue", "Namespace", + "Variable", "Typedef", "Struct", "Union", "StaticVariable", + "Interface", "Parameter", "If", "Scope", "Do", + "Switch", "While", "For"}; return arr[uint32_t(type)]; } @@ -2084,33 +2061,34 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, break; } + case D3D12_HLSL_NODE_TYPE_WHILE: + case D3D12_HLSL_NODE_TYPE_FOR: + case D3D12_HLSL_NODE_TYPE_SWITCH: case D3D12_HLSL_NODE_TYPE_IF: { - const DxcHLSLIf &If = Refl.Ifs[localId]; - const DxcHLSLNode &Node = Refl.Nodes[If.NodeId]; - - uint32_t elseNodes = - Node.GetChildCount() - If.GetIfNodes() - If.HasConditionVar(); - - if (elseNodes || If.GetIfNodes() || If.HasConditionVar() || - If.HasElse()) - printf("%sif nodes: %u, else nodes: %u%s%s\n", - std::string(Depth, '\t').c_str(), If.GetIfNodes(), elseNodes, - If.HasConditionVar() ? " (has cond var)" : "", - If.HasElse() ? " (has else)" : ""); + const DxcHLSLStatement &Stmt = Refl.Statements[localId]; + const DxcHLSLNode &Node = Refl.Nodes[Stmt.NodeId]; - break; - } + uint32_t bodyNodes = + Node.GetChildCount() - Stmt.GetNodeCount() - Stmt.HasConditionVar(); - case D3D12_HLSL_NODE_TYPE_FORWHILESWITCH: { + bool isIf = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF; + bool isFor = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_FOR; - const DxcHLSLForWhileSwitch &ForWhileSwitch = - Refl.ForWhileSwitches[localId]; + if (bodyNodes || Stmt.GetNodeCount() || Stmt.HasConditionVar() || + Stmt.HasElse()) { - static const char *types[] = {"For", "While", "Switch"}; + if (isIf || isFor) + printf("%s%snodes: %u, %snodes: %u%s%s\n", + std::string(Depth, '\t').c_str(), isIf ? "if " : "init ", + Stmt.GetNodeCount(), isIf ? "else " : "body ", bodyNodes, + Stmt.HasConditionVar() ? " (has cond var)" : "", + Stmt.HasElse() ? " (has else)" : ""); - printf("%s%s\n", std::string(Depth, '\t').c_str(), - types[ForWhileSwitch.GetType()]); + else + printf("%sbody nodes: %u%s\n", std::string(Depth, '\t').c_str(), + bodyNodes, Stmt.HasConditionVar() ? " (has cond var)" : ""); + } break; } @@ -2193,8 +2171,8 @@ struct DxcHLSLHeader { uint32_t TypeListCount; uint32_t Parameters; - uint32_t Ifs; - uint32_t ForWhileSwitches; + uint32_t Statements; + uint32_t Pad; }; template @@ -2453,7 +2431,7 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, TypeNameIds, - Buffers, Parameters, Ifs, ForWhileSwitches); + Buffers, Parameters, Statements); Bytes.resize(toReserve); @@ -2469,15 +2447,14 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { uint32_t(Arrays.size()), uint32_t(ArraySizes.size()), uint32_t(MemberTypeIds.size()), uint32_t(Types.size()), uint32_t(Buffers.size()), uint32_t(TypeList.size()), - uint32_t(Parameters.size()), uint32_t(Ifs.size()), - uint32_t(ForWhileSwitches.size())}; + uint32_t(Parameters.size()), uint32_t(Statements.size())}; toReserve += sizeof(DxcHLSLHeader); Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, - TypeNameIds, Buffers, Parameters, Ifs, ForWhileSwitches); + TypeNameIds, Buffers, Parameters, Statements); } DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes, @@ -2512,8 +2489,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes Arrays, header.Arrays, MemberTypeIds, header.Members, TypeList, header.TypeListCount, MemberNameIds, memberSymbolCount, Types, header.Types, TypeNameIds, typeSymbolCount, Buffers, header.Buffers, - Parameters, header.Parameters, Ifs, header.Ifs, ForWhileSwitches, - header.ForWhileSwitches); + Parameters, header.Parameters, Statements, header.Statements); // Validation errors are throws to prevent accessing invalid data @@ -2580,30 +2556,34 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes break; - case D3D12_HLSL_NODE_TYPE_IF: case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: - case D3D12_HLSL_NODE_TYPE_FORWHILESWITCH: + case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_FOR: + case D3D12_HLSL_NODE_TYPE_WHILE: + case D3D12_HLSL_NODE_TYPE_SWITCH: - maxValue = - node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF - ? header.Ifs - : (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_FORWHILESWITCH - ? header.ForWhileSwitches - : 1); + maxValue = node.GetNodeType() != D3D12_HLSL_NODE_TYPE_SCOPE && + node.GetNodeType() != D3D12_HLSL_NODE_TYPE_DO + ? header.Statements + : 1; - if (Nodes[node.GetParentId()].GetNodeType() != - D3D12_HLSL_NODE_TYPE_FUNCTION && - Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_IF && - Nodes[node.GetParentId()].GetNodeType() != - D3D12_HLSL_NODE_TYPE_SCOPE && - Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_DO && - Nodes[node.GetParentId()].GetNodeType() != - D3D12_HLSL_NODE_TYPE_FORWHILESWITCH) + switch (Nodes[node.GetParentId()].GetNodeType()) { + case D3D12_HLSL_NODE_TYPE_FUNCTION: + case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_SCOPE: + case D3D12_HLSL_NODE_TYPE_DO: + case D3D12_HLSL_NODE_TYPE_FOR: + case D3D12_HLSL_NODE_TYPE_WHILE: + case D3D12_HLSL_NODE_TYPE_SWITCH: + break; + + default: throw std::invalid_argument( "Node " + std::to_string(i) + " is an if/scope/do/for/while/switch but parent isn't of a similar " "type or function"); + } break; @@ -2636,7 +2616,9 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_IF: case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: - case D3D12_HLSL_NODE_TYPE_FORWHILESWITCH: + case D3D12_HLSL_NODE_TYPE_FOR: + case D3D12_HLSL_NODE_TYPE_WHILE: + case D3D12_HLSL_NODE_TYPE_SWITCH: if (node.GetChildCount()) validateChildren.push_back(i); } @@ -2856,7 +2838,9 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_ENUM: case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: - case D3D12_HLSL_NODE_TYPE_FORWHILESWITCH: + case D3D12_HLSL_NODE_TYPE_FOR: + case D3D12_HLSL_NODE_TYPE_WHILE: + case D3D12_HLSL_NODE_TYPE_SWITCH: break; default: throw std::invalid_argument( @@ -2868,55 +2852,38 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes } } - for (uint32_t i = 0; i < header.Ifs; ++i) { + for (uint32_t i = 0; i < header.Statements; ++i) { - const DxcHLSLIf &If = Ifs[i]; + const DxcHLSLStatement &Stmt = Statements[i]; - if (If.NodeId >= header.Nodes || - Nodes[If.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_IF || - Nodes[If.NodeId].GetLocalId() != i) - throw std::invalid_argument("If " + std::to_string(i) + + if (Stmt.NodeId >= header.Nodes || Nodes[Stmt.NodeId].GetLocalId() != i) + throw std::invalid_argument("Statement " + std::to_string(i) + " points to an invalid nodeId"); - bool ifCondVar = If.HasConditionVar(); - uint32_t minParamCount = If.GetIfNodes() + ifCondVar; - const DxcHLSLNode &node = Nodes[If.NodeId]; + bool condVar = Stmt.HasConditionVar(); + uint32_t minParamCount = Stmt.GetNodeCount() + condVar; + const DxcHLSLNode &node = Nodes[Stmt.NodeId]; if (node.GetChildCount() < minParamCount) - throw std::invalid_argument("If " + std::to_string(i) + + throw std::invalid_argument("Statement " + std::to_string(i) + " didn't have required child nodes"); - if (ifCondVar && - Nodes[If.NodeId + 1].GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) + if (condVar && + Nodes[Stmt.NodeId + 1].GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) throw std::invalid_argument( - "If " + std::to_string(i) + + "Statement " + std::to_string(i) + " has condition variable but first child is not a variable"); - } - - for (uint32_t i = 0; i < header.ForWhileSwitches; ++i) { - const DxcHLSLForWhileSwitch &ForWhileSwitch = ForWhileSwitches[i]; - - if (ForWhileSwitch.NodeId >= header.Nodes || - Nodes[ForWhileSwitch.NodeId].GetNodeType() != - D3D12_HLSL_NODE_TYPE_FORWHILESWITCH || - Nodes[ForWhileSwitch.NodeId].GetLocalId() != i) - throw std::invalid_argument("ForWhileSwitch " + std::to_string(i) + - " points to an invalid nodeId"); - - bool ifCondVar = ForWhileSwitch.HasConditionVar(); - uint32_t minParamCount = ifCondVar; - const DxcHLSLNode &node = Nodes[ForWhileSwitch.NodeId]; - - if (node.GetChildCount() < minParamCount) - throw std::invalid_argument("ForWhileSwitch " + std::to_string(i) + - " didn't have required child nodes"); - - if (ifCondVar && Nodes[ForWhileSwitch.NodeId + 1].GetNodeType() != - D3D12_HLSL_NODE_TYPE_VARIABLE) - throw std::invalid_argument( - "ForWhileSwitch " + std::to_string(i) + - " has condition variable but first child is not a variable"); + switch (Nodes[Stmt.NodeId].GetNodeType()) { + case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_WHILE: + case D3D12_HLSL_NODE_TYPE_FOR: + case D3D12_HLSL_NODE_TYPE_SWITCH: + break; + default: + throw std::invalid_argument("Statement " + std::to_string(i) + + " has invalid node type"); + } } for (uint32_t i = 0; i < header.Types; ++i) { From 8be6f762770ebaff6de1092ae260f9abd92a7ab1 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 22 Oct 2025 23:17:18 +0200 Subject: [PATCH 060/126] Added DxcHLSLArrayOrElements to wrap the concept of having either an array id or elements, since there are now two occurrences of it. Renamed ElementsOrArrayId to UnderlyingArray to handle the fact that the type we create will be the underlying type with the underlying array size (e.g. F32x4a4[4] turns into float4[4][4] while the pretty type will stay as F32x4a4[4]). Fixed a mistake where after array traversal an underlying type would get its array back. Type now has a TypeSymbol rather than only a nameId. Added support for groupshared variables. Added D3D12_SHADER_TYPE_DESC1 and extended ID3D12ShaderReflectionType1 to make up for the fact that display name & array can't be queried. --- include/dxc/DxcReflection/DxcReflection.h | 83 ++++-- include/dxc/dxctools.h | 18 +- .../tools/dxcreflection/DxcReflection.cpp | 248 +++++++++++++----- tools/clang/tools/libclang/dxcreflector.cpp | 105 +++++--- 4 files changed, 327 insertions(+), 127 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 9941c7868d..ec30822763 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -441,6 +441,34 @@ struct DxcHLSLArray { uint32_t ArrayStart() const { return ArrayElemStart << 6 >> 6; } }; +struct DxcHLSLArrayOrElements { + + uint32_t ElementsOrArrayId; + + DxcHLSLArrayOrElements() = default; + DxcHLSLArrayOrElements(uint32_t arrayId, uint32_t arraySize) + : ElementsOrArrayId(arrayId != (uint32_t)-1 + ? ((1u << 31) | arrayId) + : (arraySize > 1 ? arraySize : 0)) {} + + bool IsMultiDimensionalArray() const { return ElementsOrArrayId >> 31; } + bool IsArray() const { return ElementsOrArrayId; } + bool Is1DArray() const { return IsArray() && !IsMultiDimensionalArray(); } + + uint32_t Get1DElements() const { + return IsMultiDimensionalArray() ? 0 : ElementsOrArrayId; + } + + uint32_t GetMultiDimensionalArrayId() const { + return IsMultiDimensionalArray() ? (ElementsOrArrayId << 1 >> 1) + : (uint32_t)-1; + } + + bool operator==(const DxcHLSLArrayOrElements &Other) const { + return Other.ElementsOrArrayId == ElementsOrArrayId; + } +}; + struct DxcHLSLType { // Almost maps to CShaderReflectionType and // D3D12_SHADER_TYPE_DESC, but tightly packed and // easily serializable @@ -457,14 +485,14 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and uint32_t ClassTypeRowsColums; }; - uint32_t ElementsOrArrayId; - uint32_t BaseClass; // -1 if none, otherwise a type index - + uint32_t BaseClass; // -1 if none, otherwise a type index uint32_t InterfaceOffsetAndCount; // 24 : 8 (start, count) + DxcHLSLArrayOrElements UnderlyingArray; //No sugar (e.g. F32x4a4 in using F32x4a4 = F32x4[4] becomes float4[4]) + bool operator==(const DxcHLSLType &Other) const { return Other.MemberData == MemberData && - Other.ElementsOrArrayId == ElementsOrArrayId && + Other.UnderlyingArray == UnderlyingArray && ClassTypeRowsColums == Other.ClassTypeRowsColums && BaseClass == Other.BaseClass && InterfaceOffsetAndCount == Other.InterfaceOffsetAndCount; @@ -478,28 +506,16 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and return InterfaceOffsetAndCount << 8 >> 8; } - bool IsMultiDimensionalArray() const { return ElementsOrArrayId >> 31; } - bool IsArray() const { return ElementsOrArrayId; } - bool Is1DArray() const { return IsArray() && !IsMultiDimensionalArray(); } - - uint32_t Get1DElements() const { - return IsMultiDimensionalArray() ? 0 : ElementsOrArrayId; - } - - uint32_t GetMultiDimensionalArrayId() const { - return IsMultiDimensionalArray() ? (ElementsOrArrayId << 1 >> 1) - : (uint32_t)-1; - } - DxcHLSLType() = default; - DxcHLSLType(uint32_t BaseClass, uint32_t ElementsOrArrayId, + DxcHLSLType(uint32_t BaseClass, + DxcHLSLArrayOrElements ElementsOrArrayIdUnderlying, D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE Type, uint8_t Rows, uint8_t Columns, uint32_t MembersCount, uint32_t MembersStart, uint32_t InterfaceOffset, uint32_t InterfaceCount) : MemberData(MembersStart | (MembersCount << 24)), Class(Class), Type(Type), Rows(Rows), Columns(Columns), - ElementsOrArrayId(ElementsOrArrayId), BaseClass(BaseClass), + UnderlyingArray(ElementsOrArrayIdUnderlying), BaseClass(BaseClass), InterfaceOffsetAndCount(InterfaceOffset | (InterfaceCount << 24)) { if (Class < D3D_SVC_SCALAR || Class > D3D_SVC_INTERFACE_POINTER) @@ -522,6 +538,31 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and } }; +struct DxcHLSLTypeSymbol { + + // Keep sugar (F32x4a4 = F32x4[4] stays F32x4a4, doesn't become float4[4] like + // in underlying name + array) + DxcHLSLArrayOrElements DisplayArray; + + // For example F32x4[4] stays F32x4 (array in DisplayArray) + uint32_t DisplayNameId; + + // F32x4[4] would turn into float4 (array in UnderlyingArray) + uint32_t UnderlyingNameId; + + bool operator==(const DxcHLSLTypeSymbol &Other) const { + return Other.DisplayArray == DisplayArray && + DisplayNameId == Other.DisplayNameId && + UnderlyingNameId == Other.UnderlyingNameId; + } + + DxcHLSLTypeSymbol() = default; + DxcHLSLTypeSymbol(DxcHLSLArrayOrElements ElementsOrArrayIdDisplay, + uint32_t DisplayNameId, uint32_t UnderlyingNameId) + : DisplayArray(ElementsOrArrayIdDisplay), DisplayNameId(DisplayNameId), + UnderlyingNameId(UnderlyingNameId) {} +}; + struct DxcHLSLBuffer { // Almost maps to CShaderReflectionConstantBuffer and // D3D12_SHADER_BUFFER_DESC @@ -600,7 +641,7 @@ struct DxcHLSLReflectionData { std::vector NodeSymbols; std::vector MemberNameIds; - std::vector TypeNameIds; + std::vector TypeSymbols; // Only generated if deserialized with MakeNameLookupTable or // GenerateNameLookupTable is called (and if symbols aren't stripped) @@ -639,7 +680,7 @@ struct DxcHLSLReflectionData { return IsSameNonDebug(Other) && Strings == Other.Strings && Sources == Other.Sources && NodeSymbols == Other.NodeSymbols && MemberNameIds == Other.MemberNameIds && - TypeNameIds == Other.TypeNameIds; + TypeSymbols == Other.TypeSymbols; } }; diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 646f962688..f2acaef134 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -195,6 +195,8 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_WHILE, D3D12_HLSL_NODE_TYPE_FOR, + D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE, + // TODO: D3D12_HLSL_NODE_TYPE_USING, D3D12_HLSL_NODE_TYPE_RESERVED = @@ -203,7 +205,7 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, // Don't forget to properly update NodeTypeToString - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_FOR + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE }; struct D3D12_HLSL_NODE { @@ -229,8 +231,8 @@ struct D3D12_HLSL_NODE_SYMBOL { // TODO: Move to d3d12shader.h struct D3D12_ARRAY_DESC { - uint32_t ArrayDims; - uint32_t ArrayLengths[32]; // SPV_REFLECT_MAX_ARRAY_DIMS + UINT ArrayDims; + UINT ArrayLengths[32]; // SPV_REFLECT_MAX_ARRAY_DIMS }; struct D3D12_SHADER_INPUT_BIND_DESC1 { @@ -238,8 +240,16 @@ struct D3D12_SHADER_INPUT_BIND_DESC1 { D3D12_ARRAY_DESC ArrayInfo; }; +typedef struct _D3D12_SHADER_TYPE_DESC1 { + D3D12_SHADER_TYPE_DESC Desc; + LPCSTR DisplayName; // Display name (not underlying name) + UINT DisplayElements; +} D3D12_SHADER_TYPE_DESC1; + DECLARE_INTERFACE_(ID3D12ShaderReflectionType1, ID3D12ShaderReflectionType) { - STDMETHOD(GetArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC * pArrayDesc) PURE; + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_TYPE_DESC1 *pDesc) PURE; + STDMETHOD(GetArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) PURE; + STDMETHOD(GetDisplayArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) PURE; }; typedef interface IDxcHLSLReflection IDxcHLSLReflection; diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 9327f63765..a86e12b4e9 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -594,21 +594,33 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, QualType Original, bool DefaultRowMaj) { // Unwrap array + // There's the following issue: + // Let's say the underlying type is F32x4[4] but the sugared name is F32x4x4, + // then we want to maintain sugared name + array info (of sugar) for reflection + // but for low level type info, we would want to know float4[4] - uint32_t arraySize = 1; - QualType underlying = Original, forName = Original.getNonReferenceType(); - std::vector arrayElem; + uint32_t arraySizeUnderlying = 1; + QualType underlying = Original.getNonReferenceType().getCanonicalType(); + std::vector arrayElemUnderlying; while (const ConstantArrayType *arr = dyn_cast(underlying)) { uint32_t current = arr->getSize().getZExtValue(); - arrayElem.push_back(current); - arraySize *= arr->getSize().getZExtValue(); - forName = arr->getElementType().getNonReferenceType(); - underlying = forName.getCanonicalType(); + arrayElemUnderlying.push_back(current); + arraySizeUnderlying *= arr->getSize().getZExtValue(); + underlying = arr->getElementType().getNonReferenceType().getCanonicalType(); } - underlying = underlying.getNonReferenceType().getCanonicalType(); + uint32_t arraySizeDisplay = 1; + std::vector arrayElemDisplay; + QualType display = Original.getNonReferenceType(); + + while (const ConstantArrayType *arr = dyn_cast(display)) { + uint32_t current = arr->getSize().getZExtValue(); + arrayElemDisplay.push_back(current); + arraySizeDisplay *= arr->getSize().getZExtValue(); + display = arr->getElementType().getNonReferenceType(); + } // Name; Omit struct, class and const keywords @@ -617,16 +629,17 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, policy.AnonymousTagLocations = false; policy.SuppressTagKeyword = true; - std::string typeName = - forName.getUnqualifiedType().getAsString(policy); + display = display.getUnqualifiedType(); + std::string displayName = display.getAsString(policy); + + std::string underlyingName = + underlying.getUnqualifiedType().getAsString(policy); //Prune template instantiation from type name for builtin types (ex. vector & matrix) //But only if it's not a sugared type: // typedef ConstantBuffer MyTest; //In this case, MyTest will still be seen as a ConstantBuffer but the typeName is MyTest. - forName = forName.getUnqualifiedType(); - static const std::unordered_map lookup = std::unordered_map{ {{"vector", D3D_SHADER_VARIABLE_TYPE(-1)}, @@ -657,7 +670,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, {"ConstantBuffer", D3D_SVT_CBUFFER}}}; if (const TemplateSpecializationType *spec = - dyn_cast(forName.getTypePtr())) { + dyn_cast(display.getTypePtr())) { const TemplateDecl *td = spec->getTemplateName().getAsTemplateDecl(); @@ -665,21 +678,23 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, auto it = lookup.find(td->getName()); - if (it != lookup.end() && it->second >= 0) - typeName = it->first; + if (it != lookup.end()) { + + if(it->second >= 0) + displayName = underlyingName = it->first; + } } } bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - uint32_t arrayId = PushArray(Refl, arraySize, arrayElem); - uint32_t elementsOrArrayId = 0; + //Two arrays; for display and for underlying - if (arrayId != (uint32_t)-1) - elementsOrArrayId = (1u << 31) | arrayId; + uint32_t arrayIdUnderlying = PushArray(Refl, arraySizeUnderlying, arrayElemUnderlying); + DxcHLSLArrayOrElements elementsOrArrayIdUnderlying(arrayIdUnderlying, arraySizeUnderlying); - else - elementsOrArrayId = arraySize > 1 ? arraySize : 0; + uint32_t arrayIdDisplay = PushArray(Refl, arraySizeDisplay, arrayElemDisplay); + DxcHLSLArrayOrElements elementsOrArrayIdDisplay(arrayIdDisplay, arraySizeDisplay); //Unwrap vector and matrix //And base type @@ -773,7 +788,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, innerTypeName = "$Element"; const TemplateSpecializationType *templateDesc = - forName->getAs(); + display->getAs(); assert(templateDesc && "Expected a valid TemplateSpecializationType"); innerType = templateDesc->getArg(0).getAsType(); @@ -912,63 +927,78 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, case BuiltinType::Min10Float: type = D3D_SVT_MIN10FLOAT; + underlyingName = "min10float"; break; case BuiltinType::Min16Float: type = D3D_SVT_MIN16FLOAT; + underlyingName = "min16float"; break; case BuiltinType::HalfFloat: case BuiltinType::Half: type = D3D_SVT_FLOAT16; + underlyingName = "float16_t"; //TODO: half or float16_t? break; case BuiltinType::Short: type = D3D_SVT_INT16; + underlyingName = "int16_t"; break; case BuiltinType::Min12Int: type = D3D_SVT_MIN12INT; + underlyingName = "min12int"; break; case BuiltinType::Min16Int: type = D3D_SVT_MIN16INT; + underlyingName = "min16int"; break; case BuiltinType::Min16UInt: type = D3D_SVT_MIN16UINT; + underlyingName = "min16uint"; break; case BuiltinType::UShort: type = D3D_SVT_UINT16; + underlyingName = "uint16_t"; break; case BuiltinType::Float: type = D3D_SVT_FLOAT; + underlyingName = "float"; break; case BuiltinType::Int: type = D3D_SVT_INT; + underlyingName = "int"; break; case BuiltinType::UInt: type = D3D_SVT_UINT; + underlyingName = "uint"; break; case BuiltinType::Bool: type = D3D_SVT_BOOL; + underlyingName = "bool"; break; case BuiltinType::Double: type = D3D_SVT_DOUBLE; + underlyingName = "double"; break; case BuiltinType::ULongLong: type = D3D_SVT_UINT64; + underlyingName = "uint64_t"; break; case BuiltinType::LongLong: type = D3D_SVT_INT64; + underlyingName = "int64_t"; break; default: @@ -976,6 +1006,25 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, } } + //Turn into proper fully qualified name (e.g. turn vector into float4) + + switch (cls) { + + case D3D_SVC_MATRIX_ROWS: + case D3D_SVC_VECTOR: + + underlyingName += std::to_string(columns); + + if (cls == D3D_SVC_MATRIX_ROWS) + underlyingName += "x" + std::to_string(rows); + + break; + + case D3D_SVC_MATRIX_COLUMNS: + underlyingName += std::to_string(rows) + "x" + std::to_string(columns); + break; + } + //Insert if (Refl.Types.size() >= uint32_t(-1)) @@ -988,23 +1037,31 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, uint8_t interfaceCount = 0; RegisterTypeList(Refl, interfaces, interfaceOffset, interfaceCount); - DxcHLSLType hlslType(baseType, elementsOrArrayId, cls, type, rows, columns, - membersCount, membersOffset, interfaceOffset, interfaceCount); + DxcHLSLType hlslType(baseType, elementsOrArrayIdUnderlying, cls, type, rows, columns, + membersCount, membersOffset, interfaceOffset, + interfaceCount); + + uint32_t displayNameId = + hasSymbols ? RegisterString(Refl, displayName, false) : uint32_t(-1); - uint32_t nameId = - hasSymbols ? RegisterString(Refl, typeName, false) : uint32_t(-1); + uint32_t underlyingNameId = + hasSymbols ? RegisterString(Refl, underlyingName, false) : uint32_t(-1); + + DxcHLSLTypeSymbol typeSymbol(elementsOrArrayIdDisplay, displayNameId, + underlyingNameId); uint32_t i = 0; uint32_t j = uint32_t(Refl.Types.size()); for (; i < j; ++i) - if (Refl.Types[i] == hlslType && (!hasSymbols || Refl.TypeNameIds[i] == nameId)) + if (Refl.Types[i] == hlslType && + (!hasSymbols || Refl.TypeSymbols[i] == typeSymbol)) break; if (i == j) { if (hasSymbols) - Refl.TypeNameIds.push_back(nameId); + Refl.TypeSymbols.push_back(typeSymbol); Refl.Types.push_back(hlslType); } @@ -1596,8 +1653,24 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, VarDecl *varDecl = dyn_cast(it); - if (varDecl && varDecl->getStorageClass() == StorageClass::SC_Static && - !varDecl->hasAttr()) { + if (varDecl && varDecl->hasAttr()) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + const std::string &name = ValDecl->getName(); + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, ValDecl->getType(), DefaultRowMaj); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, + D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE, ParentNodeId, + typeId); + + continue; + } + + if (varDecl && varDecl->getStorageClass() == StorageClass::SC_Static) { if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) continue; @@ -1629,8 +1702,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, // Handle $Globals if (varDecl && - (Depth == 0 || Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES) && - !varDecl->hasAttr()) { + (Depth == 0 || Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { const std::string &name = ValDecl->getName(); @@ -1780,15 +1852,50 @@ static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { - static const char *arr[] = { - "Register", "Function", "Enum", "EnumValue", "Namespace", - "Variable", "Typedef", "Struct", "Union", "StaticVariable", - "Interface", "Parameter", "If", "Scope", "Do", - "Switch", "While", "For"}; + static const char *arr[] = {"Register", + "Function", + "Enum", + "EnumValue", + "Namespace", + "Variable", + "Typedef", + "Struct", + "Union", + "StaticVariable", + "Interface", + "Parameter", + "If", + "Scope", + "Do", + "Switch", + "While", + "For", + "GroupsharedVariable"}; return arr[uint32_t(type)]; } +static std::string +PrintArray(const DxcHLSLReflectionData &Refl, const DxcHLSLArrayOrElements &Arr) { + + std::string result; + + if (Arr.IsMultiDimensionalArray()) { + + const DxcHLSLArray &arr = Refl.Arrays[Arr.GetMultiDimensionalArrayId()]; + + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) + result += + "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart() + i]) + "]"; + + } + + else if (Arr.IsArray()) + result += "[" + std::to_string(Arr.Get1DElements()) + "]"; + + return result; +} + static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, const DxcHLSLType &Type) { @@ -1887,30 +1994,18 @@ static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, } static std::string PrintTypeInfo(const DxcHLSLReflectionData &Refl, - const DxcHLSLType &Type, - const std::string &PreviousTypeName) { - - std::string result; - - if (Type.IsMultiDimensionalArray()) { + const DxcHLSLType &Type, + const DxcHLSLTypeSymbol &Symbol, + const std::string &PreviousTypeName) { - const DxcHLSLArray &arr = Refl.Arrays[Type.GetMultiDimensionalArrayId()]; - - for (uint32_t i = 0; i < arr.ArrayElem(); ++i) - result += - "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart() + i]) + "]"; - - } - - else if (Type.IsArray()) - result += "[" + std::to_string(Type.Get1DElements()) + "]"; + std::string result = PrintArray(Refl, Type.UnderlyingArray); // Obtain type name (returns empty if it's not a builtin type) - std::string underlyingTypeName = GetBuiltinTypeName(Refl, Type); - - if (PreviousTypeName != underlyingTypeName && underlyingTypeName.size()) - result += " (" + underlyingTypeName + ")"; + if (Symbol.DisplayNameId != Symbol.UnderlyingNameId && + Symbol.UnderlyingNameId) + result += " (" + Refl.Strings[Symbol.DisplayNameId] + + PrintArray(Refl, Symbol.DisplayArray) + ")"; return result; } @@ -1922,14 +2017,17 @@ static void RecursePrintType(const DxcHLSLReflectionData &Refl, uint32_t TypeId, bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - std::string name = hasSymbols ? Refl.Strings[Refl.TypeNameIds[TypeId]] + DxcHLSLTypeSymbol symbol = + hasSymbols ? Refl.TypeSymbols[TypeId] : DxcHLSLTypeSymbol(); + + std::string name = hasSymbols ? Refl.Strings[symbol.UnderlyingNameId] : GetBuiltinTypeName(Refl, type); if (name.empty() && !hasSymbols) name = "(unknown)"; printf("%s%s%s%s\n", std::string(Depth, '\t').c_str(), Prefix, name.c_str(), - PrintTypeInfo(Refl, type, name).c_str()); + PrintTypeInfo(Refl, type, symbol, name).c_str()); if (type.BaseClass != uint32_t(-1)) RecursePrintType(Refl, type.BaseClass, Depth + 1, @@ -2096,6 +2194,7 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: + case D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE: typeToPrint = localId; break; @@ -2340,7 +2439,7 @@ void DxcHLSLReflectionData::StripSymbols() { NodeIdToFullyResolved.clear(); FullyResolvedToMemberId.clear(); NodeSymbols.clear(); - TypeNameIds.clear(); + TypeSymbols.clear(); MemberNameIds.clear(); Features &= ~D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; } @@ -2387,7 +2486,8 @@ uint32_t RecurseNameGeneration(DxcHLSLReflectionData &Refl, uint32_t NodeId, bool isDotChild = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_REGISTER; bool isVar = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_VARIABLE || - node.GetNodeType() == D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE; + node.GetNodeType() == D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE || + node.GetNodeType() == D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE; for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) i += RecurseNameGeneration(Refl, NodeId + 1 + i, j, self, isDotChild); @@ -2430,7 +2530,7 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, - Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, TypeNameIds, + Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, TypeSymbols, Buffers, Parameters, Statements); Bytes.resize(toReserve); @@ -2454,7 +2554,7 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, - TypeNameIds, Buffers, Parameters, Statements); + TypeSymbols, Buffers, Parameters, Statements); } DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes, @@ -2488,7 +2588,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes Annotations, header.Annotations, ArraySizes, header.ArraySizes, Arrays, header.Arrays, MemberTypeIds, header.Members, TypeList, header.TypeListCount, MemberNameIds, memberSymbolCount, Types, - header.Types, TypeNameIds, typeSymbolCount, Buffers, header.Buffers, + header.Types, TypeSymbols, typeSymbolCount, Buffers, header.Buffers, Parameters, header.Parameters, Statements, header.Statements); // Validation errors are throws to prevent accessing invalid data @@ -2591,6 +2691,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: + case D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE: maxValue = header.Types; break; @@ -2607,6 +2708,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: + case D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE: case D3D12_HLSL_NODE_TYPE_PARAMETER: if (node.GetChildCount()) throw std::invalid_argument("Node " + std::to_string(i) + @@ -2890,18 +2992,26 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLType &type = Types[i]; - if (hasSymbolInfo && TypeNameIds[i] >= header.Strings) + if (hasSymbolInfo && (TypeSymbols[i].DisplayNameId >= header.Strings || + TypeSymbols[i].UnderlyingNameId >= header.Strings)) + throw std::invalid_argument("Type " + std::to_string(i) + + " points to an invalid string"); + + if (hasSymbolInfo && (TypeSymbols[i].DisplayArray.ElementsOrArrayId >> 31 && + (TypeSymbols[i].DisplayArray.ElementsOrArrayId << 1 >> + 1) >= header.Arrays)) throw std::invalid_argument("Type " + std::to_string(i) + " points to an invalid string"); if ((type.BaseClass != uint32_t(-1) && type.BaseClass >= header.Types) || type.GetMemberStart() + type.GetMemberCount() > header.Members || - type.GetInterfaceStart() + type.GetInterfaceCount() > header.TypeListCount || - (type.ElementsOrArrayId >> 31 && - (type.ElementsOrArrayId << 1 >> 1) >= header.Arrays)) + type.GetInterfaceStart() + type.GetInterfaceCount() > + header.TypeListCount || + (type.UnderlyingArray.ElementsOrArrayId >> 31 && + (type.UnderlyingArray.ElementsOrArrayId << 1 >> 1) >= header.Arrays)) throw std::invalid_argument( "Type " + std::to_string(i) + - " points to an invalid string, base class or member"); + " points to an invalid string, array, base class or member"); switch (type.Class) { diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 385711d297..8aaa4670cc 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -152,7 +152,8 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { protected: - std::string m_Name; + std::string m_NameUnderlying; + std::string m_NameDisplay; std::vector m_MemberNames; std::unordered_map m_NameToMemberId; std::vector m_MemberTypes; @@ -161,8 +162,39 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { const DxcHLSLReflectionData *m_Data; uint32_t m_TypeId; - uint32_t m_Elements; - D3D12_ARRAY_DESC m_ArrayDesc; + uint32_t m_ElementsUnderlying; + uint32_t m_ElementsDisplay; + D3D12_ARRAY_DESC m_ArrayDescUnderlying; + D3D12_ARRAY_DESC m_ArrayDescDisplay; + + void InitializeArray(const DxcHLSLReflectionData &Data, + D3D12_ARRAY_DESC &desc, uint32_t &elements, + const DxcHLSLArrayOrElements &arrElem) { + + if (arrElem.IsArray()) { + + elements = arrElem.Is1DArray() ? arrElem.Get1DElements() : 1; + + if (arrElem.IsMultiDimensionalArray()) { + + const DxcHLSLArray &arr = + Data.Arrays[arrElem.GetMultiDimensionalArrayId()]; + + desc.ArrayDims = arr.ArrayElem(); + + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) { + uint32_t len = Data.ArraySizes[arr.ArrayStart() + i]; + elements *= len; + desc.ArrayLengths[i] = len; + } + } + + else { + desc.ArrayDims = 1; + desc.ArrayLengths[0] = arrElem.Get1DElements(); + } + } + } public: @@ -186,7 +218,16 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { if (!pArrayDesc) return E_POINTER; - *pArrayDesc = m_ArrayDesc; + *pArrayDesc = m_ArrayDescUnderlying; + return S_OK; + } + + STDMETHOD(GetDisplayArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) override { + + if (!pArrayDesc) + return E_POINTER; + + *pArrayDesc = m_ArrayDescDisplay; return S_OK; } @@ -195,41 +236,26 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { std::vector &Types /* Only access < TypeId*/) { m_TypeId = TypeId; - m_Elements = 0; + m_ElementsUnderlying = 0; + m_ElementsDisplay = 0; m_Data = &Data; - ZeroMemoryToOut(&m_ArrayDesc); - const DxcHLSLType &type = Data.Types[TypeId]; - if (type.IsArray()) { - - m_Elements = type.Is1DArray() ? type.Get1DElements() : 1; - - if (type.IsMultiDimensionalArray()) { - - const DxcHLSLArray &arr = - Data.Arrays[type.GetMultiDimensionalArrayId()]; - - m_ArrayDesc.ArrayDims = arr.ArrayElem(); + ZeroMemoryToOut(&m_ArrayDescUnderlying); + ZeroMemoryToOut(&m_ArrayDescDisplay); - for (uint32_t i = 0; i < arr.ArrayElem(); ++i) { - uint32_t len = Data.ArraySizes[arr.ArrayStart() + i]; - m_Elements *= len; - m_ArrayDesc.ArrayLengths[i] = len; - } - } - - else { - m_ArrayDesc.ArrayDims = 1; - m_ArrayDesc.ArrayLengths[0] = type.Get1DElements(); - } - } + InitializeArray(Data, m_ArrayDescUnderlying, m_ElementsUnderlying, + type.UnderlyingArray); bool hasNames = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (hasNames) - m_Name = Data.TypeNameIds[TypeId]; + if (hasNames) { + DxcHLSLTypeSymbol sym = Data.TypeSymbols[TypeId]; + m_NameUnderlying = Data.Strings[sym.UnderlyingNameId]; + m_NameDisplay = Data.Strings[sym.DisplayNameId]; + InitializeArray(Data, m_ArrayDescDisplay, m_ElementsDisplay, sym.DisplayArray); + } uint32_t memberCount = type.GetMemberCount(); @@ -278,15 +304,28 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { type.Rows, type.Columns, - m_Elements, + m_ElementsUnderlying, uint32_t(m_MemberTypes.size()), 0, //TODO: Offset if we have one - m_Name.c_str() + m_NameUnderlying.c_str() }; return S_OK; } + STDMETHOD(GetDesc)(D3D12_SHADER_TYPE_DESC1 *pDesc) override { + + IFR(ZeroMemoryToOut(pDesc)); + + const DxcHLSLType &type = m_Data->Types[m_TypeId]; + + GetDesc(&pDesc->Desc); + pDesc->DisplayName = m_NameDisplay.c_str(); + pDesc->DisplayElements = m_ElementsDisplay; + + return S_OK; + } + STDMETHOD_(ID3D12ShaderReflectionType *, GetMemberTypeByIndex) (UINT Index) override { From 382ad400f0183d128c4f83f87343796c322a6042 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Fri, 24 Oct 2025 08:06:42 +0200 Subject: [PATCH 061/126] Fixed annotations/attributes on for/if loops --- tools/clang/tools/dxcreflection/DxcReflection.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index a86e12b4e9..0cce2b363c 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -1373,6 +1373,9 @@ static void RecursiveReflectBody( if (!Statement) return; + while (const AttributedStmt *AS = dyn_cast(Statement)) + Statement = AS->getSubStmt(); + if (const IfStmt *If = dyn_cast(Statement)) GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, From e81b93c857d6cf96d9c8ae5513cdd5405b4ecbe1 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 25 Oct 2025 22:07:22 +0200 Subject: [PATCH 062/126] Removed clang dependent logic from dxcreflection to allow it to be used in any project without including llvm in theory. Moved the clang dependent stuff to dxcreflection_from_ast.cpp. --- include/dxc/DxcReflection/DxcReflection.h | 21 +- .../clang/tools/dxcreflection/CMakeLists.txt | 8 - .../tools/dxcreflection/DxcReflection.cpp | 1868 +---------------- tools/clang/tools/libclang/CMakeLists.txt | 2 + .../tools/libclang/dxcreflection_from_ast.cpp | 1643 +++++++++++++++ tools/clang/tools/libclang/dxcreflector.cpp | 15 +- 6 files changed, 1773 insertions(+), 1784 deletions(-) create mode 100644 tools/clang/tools/libclang/dxcreflection_from_ast.cpp diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index ec30822763..26bae8f513 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -13,15 +13,11 @@ #include #include #include +#include #include "d3d12shader.h" #include "dxc/dxctools.h" -namespace clang { -class TranslationUnitDecl; -class CompilerInstance; -} - #pragma warning(disable : 4201) namespace hlsl { @@ -650,6 +646,15 @@ struct DxcHLSLReflectionData { std::vector NodeIdToFullyResolved; std::unordered_map FullyResolvedToMemberId; + uint32_t RegisterString(const std::string &Name, bool IsNonDebug); + uint32_t PushArray(uint32_t ArraySizeFlat, + const std::vector &ArraySize); + + void RegisterTypeList(const std::vector &TypeIds, uint32_t &Offset, + uint8_t &Len); + + static D3D_CBUFFER_TYPE GetBufferType(uint8_t Type); + void Dump(std::vector &Bytes) const; void Printf() const; void StripSymbols(); @@ -659,12 +664,6 @@ struct DxcHLSLReflectionData { DxcHLSLReflectionData(const std::vector &Bytes, bool MakeNameLookupTable); - static bool Initialize(clang::CompilerInstance &Compiler, - clang::TranslationUnitDecl &Ctx, - uint32_t AutoBindingSpace, - D3D12_HLSL_REFLECTION_FEATURE Features, - bool DefaultRowMaj, DxcHLSLReflectionData &Result); - bool IsSameNonDebug(const DxcHLSLReflectionData &Other) const { return StringsNonDebug == Other.StringsNonDebug && Nodes == Other.Nodes && Registers == Other.Registers && Functions == Other.Functions && diff --git a/tools/clang/tools/dxcreflection/CMakeLists.txt b/tools/clang/tools/dxcreflection/CMakeLists.txt index b6820d83ba..2d4510609a 100644 --- a/tools/clang/tools/dxcreflection/CMakeLists.txt +++ b/tools/clang/tools/dxcreflection/CMakeLists.txt @@ -1,12 +1,4 @@ # Copyright (C) Microsoft Corporation. All rights reserved. # This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. -set(LIBRARIES - clangFrontend - clangAST - clangBasic - clangLex - ) - add_clang_library(dxcreflection STATIC DxcReflection.cpp) -target_link_libraries(dxcreflection PRIVATE ${LIBRARIES}) diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 0cce2b363c..75d2288eec 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -7,1823 +7,144 @@ // // /////////////////////////////////////////////////////////////////////////////// -#include "clang/AST/Attr.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/HlslTypes.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/basic/SourceManager.h" -#include "clang/Lex/Lexer.h" #include "dxc/DxcReflection/DxcReflection.h" +#include +#include #undef min #undef max -using namespace clang; - -namespace hlsl { - -struct DxcRegisterTypeInfo { - D3D_SHADER_INPUT_TYPE RegisterType; - D3D_SHADER_INPUT_FLAGS RegisterFlags; - D3D_SRV_DIMENSION TextureDimension; - D3D_RESOURCE_RETURN_TYPE TextureValue; -}; - -static uint32_t RegisterString(DxcHLSLReflectionData &Refl, - const std::string &Name, bool isNonDebug) { - - if (Name.size() >= 32768) - throw std::invalid_argument("Strings are limited to 32767"); - - if (isNonDebug) { - - if (Refl.StringsNonDebug.size() >= uint32_t(-1)) - throw std::invalid_argument("Strings overflow"); - - auto it = Refl.StringsToIdNonDebug.find(Name); - - if (it != Refl.StringsToIdNonDebug.end()) - return it->second; - - uint32_t stringId = uint32_t(Refl.StringsNonDebug.size()); - - Refl.StringsNonDebug.push_back(Name); - Refl.StringsToIdNonDebug[Name] = stringId; - return stringId; - } - - if (Refl.Strings.size() >= uint32_t(-1)) - throw std::invalid_argument("Strings overflow"); - - auto it = Refl.StringsToId.find(Name); - - if (it != Refl.StringsToId.end()) - return it->second; - - uint32_t stringId = uint32_t(Refl.Strings.size()); - - Refl.Strings.push_back(Name); - Refl.StringsToId[Name] = stringId; - return stringId; -} - -static uint32_t -PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, - const LangOptions &LangOpts, const std::string &UnqualifiedName, - const Decl *DeclSelf, D3D12_HLSL_NODE_TYPE Type, - uint32_t ParentNodeId, uint32_t LocalId, - const SourceRange *Range = nullptr, - std::unordered_map *FwdDecls = nullptr) -{ - - if (Refl.Nodes.size() >= (1u << 24)) - throw std::invalid_argument("Nodes overflow"); - - if (LocalId >= (1u << 24)) - throw std::invalid_argument("LocalId overflow"); - - uint32_t nodeId = Refl.Nodes.size(); - - uint16_t annotationStart = uint16_t(Refl.Annotations.size()); - uint8_t annotationCount = 0; - - uint16_t semanticId = uint16_t(-1); - - if (DeclSelf) { - for (const Attr *attr : DeclSelf->attrs()) { - if (const AnnotateAttr *annotate = dyn_cast(attr)) { - - if (Refl.Annotations.size() >= (1u << 16)) - throw std::invalid_argument("Out of annotations"); - - Refl.Annotations.push_back(DxcHLSLAnnotation( - RegisterString(Refl, annotate->getAnnotation().str(), true), - false)); - - if (annotationCount >= uint8_t(-1)) - throw std::invalid_argument("Annotation count out of bounds"); - - ++annotationCount; - - } else if (const HLSLShaderAttr *shaderAttr = - dyn_cast(attr)) { - - if (Refl.Annotations.size() >= (1u << 16)) - throw std::invalid_argument("Out of annotations"); - - Refl.Annotations.push_back(DxcHLSLAnnotation( - RegisterString( - Refl, "shader(\"" + shaderAttr->getStage().str() + "\")", true), - true)); - - if (annotationCount >= uint8_t(-1)) - throw std::invalid_argument("Annotation count out of bounds"); - - ++annotationCount; - - } - } - - if (const ValueDecl *valDecl = dyn_cast(DeclSelf)) { - - const ArrayRef &UA = - valDecl->getUnusualAnnotations(); - - for (auto It = UA.begin(), E = UA.end(); It != E; ++It) - if ((*It)->getKind() == hlsl::UnusualAnnotation::UA_SemanticDecl) { - semanticId = RegisterString( - Refl, cast(*It)->SemanticName.str(), true); - } - } - } - - bool isFwdDeclare = false; - bool canHaveFwdDeclare = false; - const Decl *fwdDeclare = nullptr; - - if (DeclSelf) { - - if (const FunctionDecl *func = dyn_cast(DeclSelf)) { - isFwdDeclare = !func->doesThisDeclarationHaveABody(); - fwdDeclare = func->getCanonicalDecl(); - canHaveFwdDeclare = true; - } - - else if (const EnumDecl *enm = dyn_cast(DeclSelf)) { - isFwdDeclare = !enm->isCompleteDefinition(); - fwdDeclare = enm->getCanonicalDecl(); - canHaveFwdDeclare = true; - } - - else if (const RecordDecl *rec = dyn_cast(DeclSelf)) { - - isFwdDeclare = !rec->isThisDeclarationADefinition(); - fwdDeclare = rec->getCanonicalDecl(); - canHaveFwdDeclare = true; - - if (isFwdDeclare && rec->isImplicit()) //Inner ghost node - return uint32_t(-1); - } - } - - uint32_t currId = uint32_t(Refl.Nodes.size()); - - if (canHaveFwdDeclare) { - - assert(FwdDecls && "Fwd decl requires FwdDecls map to be present"); - - // Multiple fwd declare, ignore - if (isFwdDeclare && FwdDecls->find(fwdDeclare) != FwdDecls->end()) - return uint32_t(-1); - - if (isFwdDeclare) - (*FwdDecls)[fwdDeclare] = currId; - } - - Refl.Nodes.push_back(DxcHLSLNode{Type, isFwdDeclare, LocalId, annotationStart, - 0, ParentNodeId, annotationCount, - semanticId}); - - if (Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { - - uint16_t sourceLineCount = 0; - uint32_t sourceLineStart = 0; - uint32_t sourceColumnStart = 0; - uint32_t sourceColumnEnd = 0; - - uint16_t sourceId = uint16_t(-1); - - SourceRange range = DeclSelf ? DeclSelf->getSourceRange() - : (Range ? *Range : SourceRange()); - - SourceLocation start = range.getBegin(); - SourceLocation end = range.getEnd(); - - if (start.isValid() && end.isValid()) { - - PresumedLoc presumed = SM.getPresumedLoc(start); - - SourceLocation realEnd = SM.getFileLoc(end); - SourceLocation endOfToken = - Lexer::getLocForEndOfToken(realEnd, 0, SM, LangOpts); - PresumedLoc presumedEnd = SM.getPresumedLoc(endOfToken); - - if (presumed.isValid() && presumedEnd.isValid()) { - - uint32_t startLine = presumed.getLine(); - uint32_t startCol = presumed.getColumn(); - uint32_t endLine = presumedEnd.getLine(); - uint32_t endCol = presumedEnd.getColumn(); - - std::string fileName = presumed.getFilename(); - - if (fileName != presumedEnd.getFilename()) - throw std::invalid_argument("End and start are not in the same file"); - - auto it = Refl.StringToSourceId.find(fileName); - uint32_t i; - - if (it == Refl.StringToSourceId.end()) { - i = (uint32_t)Refl.Sources.size(); - Refl.Sources.push_back(RegisterString(Refl, fileName, false)); - Refl.StringToSourceId[fileName] = i; - } - - else { - i = it->second; - } - - if (i >= 65535) - throw std::invalid_argument("Source file count is limited to 16-bit"); - - if ((endLine - startLine) >= 65535) - throw std::invalid_argument("Source line count is limited to 16-bit"); - - if (startLine >= 1048576) - throw std::invalid_argument("Source line start is limited to 20-bit"); - - if (startCol >= (1u << 22)) - throw std::invalid_argument("Column start is limited to 22-bit"); - - if (endCol >= (1u << 22)) - throw std::invalid_argument("Column end is limited to 22-bit"); - - sourceLineCount = uint16_t(endLine - startLine + 1); - sourceLineStart = startLine; - sourceColumnStart = startCol; - sourceColumnEnd = endCol; - sourceId = uint16_t(i); - } - } - - uint32_t nameId = RegisterString(Refl, UnqualifiedName, false); - - Refl.NodeSymbols.push_back( - DxcHLSLNodeSymbol(nameId, sourceId, sourceLineCount, sourceLineStart, - sourceColumnStart, sourceColumnEnd)); - } - - // Link - - if (DeclSelf && fwdDeclare != DeclSelf && fwdDeclare && !isFwdDeclare) { - assert(FwdDecls && "Referencing fwd decl requires FwdDecls map to be present"); - uint32_t fwd = (*FwdDecls)[fwdDeclare]; - Refl.Nodes[fwd].ResolveFwdDeclare(fwd, Refl.Nodes[currId], currId); - } - - uint32_t parentParent = ParentNodeId; - - while (parentParent != 0) { - DxcHLSLNode &parent = Refl.Nodes[parentParent]; - parent.IncreaseChildCount(); - parentParent = parent.GetParentId(); - } - - Refl.Nodes[0].IncreaseChildCount(); - - return nodeId; -} - -static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, - std::string TypeName, - bool IsWrite, - const CXXRecordDecl *RecordDecl) { - - DxcRegisterTypeInfo type = {}; - type.RegisterType = IsWrite ? D3D_SIT_UAV_RWTYPED : D3D_SIT_TEXTURE; - - //Parse return type and dimensions - - const ClassTemplateSpecializationDecl *textureTemplate = - dyn_cast(RecordDecl); - - assert(textureTemplate && "Expected texture template"); - - const ArrayRef& textureParams = textureTemplate->getTemplateArgs().asArray(); - - bool shouldBeTexture2DMS = textureParams.size() == 2; - - if (shouldBeTexture2DMS) - assert(textureParams[0].getKind() == TemplateArgument::Type && - textureParams[1].getKind() == TemplateArgument::Integral && - "Expected template args"); - - else assert(textureParams.size() == 1 && - textureParams[0].getKind() == TemplateArgument::Type && - "Expected template args"); - - QualType valueType = textureParams[0].getAsType(); - QualType desugared = valueType.getDesugaredType(ASTCtx); - - uint32_t dimensions; - - if (const BuiltinType *bt = dyn_cast(desugared)) - dimensions = 1; - - else { - - const RecordType *RT = desugared->getAs(); - assert(RT && "Expected record type"); - - const CXXRecordDecl *RD = dyn_cast(RT->getDecl()); - assert(RT && "Expected record decl"); - - const ClassTemplateSpecializationDecl *vectorType = - dyn_cast(RD); - - assert(vectorType && - "Expected vector type as template inside of texture template"); - - const ArrayRef &vectorParams = - vectorType->getTemplateArgs().asArray(); - - assert(vectorParams.size() == 2 && - vectorParams[0].getKind() == TemplateArgument::Type && - vectorParams[1].getKind() == TemplateArgument::Integral && - "Expected vector to be vector"); - - valueType = vectorParams[0].getAsType(); - desugared = valueType.getDesugaredType(ASTCtx); - - dimensions = vectorParams[1].getAsIntegral().getZExtValue(); - } - - if (desugared->isFloatingType()) { - type.TextureValue = desugared->isSpecificBuiltinType(BuiltinType::Double) - ? D3D_RETURN_TYPE_DOUBLE - : D3D_RETURN_TYPE_FLOAT; - } else if (desugared->isIntegerType()) { - const auto &semantics = ASTCtx.getTypeInfo(desugared); - if (semantics.Width == 64) { - type.TextureValue = D3D_RETURN_TYPE_MIXED; - } else { - type.TextureValue = desugared->isUnsignedIntegerType() - ? D3D_RETURN_TYPE_UINT - : D3D_RETURN_TYPE_SINT; - } - } - - else { - type.TextureValue = D3D_RETURN_TYPE_MIXED; - } - - switch (dimensions) { - case 2: - type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENT_0; - break; - case 3: - type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENT_1; - break; - case 4: - type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENTS; - break; - } - - //Parse type - - if (TypeName == "Buffer") { - assert(!shouldBeTexture2DMS && "Buffer expected but got Buffer"); - type.TextureDimension = D3D_SRV_DIMENSION_BUFFER; - return type; - } - - bool isFeedback = false; - - if (TypeName.size() > 8 && TypeName.substr(0, 8) == "Feedback") { - isFeedback = true; - TypeName = TypeName.substr(8); - type.RegisterType = D3D_SIT_UAV_FEEDBACKTEXTURE; - } - - bool isArray = false; - - if (TypeName.size() > 5 && TypeName.substr(TypeName.size() - 5) == "Array") { - isArray = true; - TypeName = TypeName.substr(0, TypeName.size() - 5); - } - - if (TypeName == "Texture2D") - type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2D; - - else if (TypeName == "TextureCube") - type.TextureDimension = D3D_SRV_DIMENSION_TEXTURECUBE; - - else if (TypeName == "Texture3D") - type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE3D; - - else if (TypeName == "Texture1D") - type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE1D; - - else if (TypeName == "Texture2DMS") - type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2DMS; - - assert((shouldBeTexture2DMS == - (type.TextureDimension == D3D_SRV_DIMENSION_TEXTURE2DMS)) && - "Texture2DMS used with Texture2D syntax or reverse"); - - if (isArray) //Arrays are always 1 behind the regular type - type.TextureDimension = (D3D_SRV_DIMENSION)(type.TextureDimension + 1); - - return type; -} - -static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, - QualType Type) { - - QualType realType = Type.getDesugaredType(ASTCtx); - const RecordType *RT = realType->getAs(); - assert(RT && "GetRegisterTypeInfo() type is not a RecordType"); - - const CXXRecordDecl *recordDecl = RT->getAsCXXRecordDecl(); - assert(recordDecl && "GetRegisterTypeInfo() type is not a CXXRecordDecl"); - - std::string typeName = recordDecl->getNameAsString(); - - if (typeName.size() >= 17 && typeName.substr(0, 17) == "RasterizerOrdered") - typeName = typeName.substr(17); - - if (typeName == "SamplerState" || typeName == "SamplerComparisonState") { - return {D3D_SIT_SAMPLER, typeName == "SamplerComparisonState" - ? D3D_SIF_COMPARISON_SAMPLER - : (D3D_SHADER_INPUT_FLAGS)0}; - } - - DxcRegisterTypeInfo info = {}; - - if (typeName == "AppendStructuredBuffer") { - info.RegisterType = D3D_SIT_UAV_APPEND_STRUCTURED; - return info; - } - - if (typeName == "ConsumeStructuredBuffer") { - info.RegisterType = D3D_SIT_UAV_CONSUME_STRUCTURED; - return info; - } - - if (typeName == "RaytracingAccelerationStructure") { - info.RegisterType = D3D_SIT_RTACCELERATIONSTRUCTURE; - return info; - } - - if (typeName == "TextureBuffer") { - info.RegisterType = D3D_SIT_TBUFFER; - return info; - } - - if (typeName == "ConstantBuffer") { - info.RegisterType = D3D_SIT_CBUFFER; - return info; - } - - bool isWrite = - typeName.size() > 2 && typeName[0] == 'R' && typeName[1] == 'W'; - - if (isWrite) - typeName = typeName.substr(2); - - if (typeName == "StructuredBuffer") { - info.RegisterType = - isWrite ? D3D_SIT_UAV_RWSTRUCTURED : D3D_SIT_STRUCTURED; - return info; - } - - if (typeName == "ByteAddressBuffer") { - info.RegisterType = - isWrite ? D3D_SIT_UAV_RWBYTEADDRESS : D3D_SIT_BYTEADDRESS; - return info; - } - - return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); -} - -static uint32_t PushArray(DxcHLSLReflectionData &Refl, uint32_t ArraySizeFlat, - const std::vector &ArraySize) { - - if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) - return uint32_t(-1); - - if (Refl.Arrays.size() >= uint32_t((1u << 31) - 1)) - throw std::invalid_argument("Arrays would overflow"); - - uint32_t arrayId = uint32_t(Refl.Arrays.size()); - - uint32_t arrayCountStart = uint32_t(Refl.ArraySizes.size()); - uint32_t numArrayElements = std::min(size_t(32), ArraySize.size()); - - if (Refl.ArraySizes.size() + numArrayElements >= ((1u << 26) - 1)) - throw std::invalid_argument("Array elements would overflow"); - - for (uint32_t i = 0; i < ArraySize.size() && i < 8; ++i) { - - uint32_t arraySize = ArraySize[i]; - - // Flatten rest of array to at least keep consistent array elements - if (i == 31) - for (uint32_t j = i + 1; j < ArraySize.size(); ++j) - arraySize *= ArraySize[j]; - - Refl.ArraySizes.push_back(arraySize); - } - - DxcHLSLArray arr = {numArrayElements, arrayCountStart}; - - for (uint32_t i = 0; i < Refl.Arrays.size(); ++i) - if (Refl.Arrays[i] == arr) - return i; - - Refl.Arrays.push_back(arr); - return arrayId; -} - -static void RegisterTypeList(DxcHLSLReflectionData &Refl, - const std::vector &TypeIds, uint32_t &Offset, - uint8_t &Len) { - - if (TypeIds.empty()) - return; - - if (TypeIds.size() >= uint8_t(-1)) - throw std::invalid_argument("Only allowing 256 types in a type list"); - - uint32_t i = 0; - uint32_t j = uint32_t(Refl.TypeList.size()); - uint32_t k = 0; - - Offset = 0; - - for (; i < j; ++i) { - - if (k == TypeIds.size()) - break; - - if (TypeIds[k] != Refl.TypeList[i]) { - - if (k) - i = Offset; - - k = 0; - break; - } - - if (!k) - Offset = i; - - ++k; - } - - if (k != TypeIds.size()) { - - uint32_t oldSiz = uint32_t(Refl.TypeList.size()); - - if (oldSiz + TypeIds.size() >= (1u << 24)) - throw std::invalid_argument("Only allowing 16Mi total interfaces"); - - Refl.TypeList.resize(oldSiz + TypeIds.size()); - - std::memcpy(Refl.TypeList.data() + oldSiz, TypeIds.data(), - TypeIds.size() * sizeof(uint32_t)); - - Offset = oldSiz; - } - - Len = uint8_t(TypeIds.size()); -} - -uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, - QualType Original, bool DefaultRowMaj) { - - // Unwrap array - // There's the following issue: - // Let's say the underlying type is F32x4[4] but the sugared name is F32x4x4, - // then we want to maintain sugared name + array info (of sugar) for reflection - // but for low level type info, we would want to know float4[4] - - uint32_t arraySizeUnderlying = 1; - QualType underlying = Original.getNonReferenceType().getCanonicalType(); - std::vector arrayElemUnderlying; - - while (const ConstantArrayType *arr = - dyn_cast(underlying)) { - uint32_t current = arr->getSize().getZExtValue(); - arrayElemUnderlying.push_back(current); - arraySizeUnderlying *= arr->getSize().getZExtValue(); - underlying = arr->getElementType().getNonReferenceType().getCanonicalType(); - } - - uint32_t arraySizeDisplay = 1; - std::vector arrayElemDisplay; - QualType display = Original.getNonReferenceType(); - - while (const ConstantArrayType *arr = dyn_cast(display)) { - uint32_t current = arr->getSize().getZExtValue(); - arrayElemDisplay.push_back(current); - arraySizeDisplay *= arr->getSize().getZExtValue(); - display = arr->getElementType().getNonReferenceType(); - } - - // Name; Omit struct, class and const keywords - - PrintingPolicy policy(ASTCtx.getLangOpts()); - policy.SuppressScope = false; - policy.AnonymousTagLocations = false; - policy.SuppressTagKeyword = true; - - display = display.getUnqualifiedType(); - std::string displayName = display.getAsString(policy); - - std::string underlyingName = - underlying.getUnqualifiedType().getAsString(policy); - - //Prune template instantiation from type name for builtin types (ex. vector & matrix) - //But only if it's not a sugared type: - // typedef ConstantBuffer MyTest; - //In this case, MyTest will still be seen as a ConstantBuffer but the typeName is MyTest. - - static const std::unordered_map - lookup = std::unordered_map{ - {{"vector", D3D_SHADER_VARIABLE_TYPE(-1)}, - {"matrix", D3D_SHADER_VARIABLE_TYPE(-2)}, - {"Texture1D", D3D_SVT_TEXTURE1D}, - {"Texture2D", D3D_SVT_TEXTURE2D}, - {"RWTexture1D", D3D_SVT_RWTEXTURE1D}, - {"RWTexture2D", D3D_SVT_RWTEXTURE2D}, - {"Texture2DMS", D3D_SVT_TEXTURE2DMS}, - {"Texture3D", D3D_SVT_TEXTURE3D}, - {"RWTexture3D", D3D_SVT_RWTEXTURE3D}, - {"TextureCube", D3D_SVT_TEXTURECUBE}, - {"Texture1DArray", D3D_SVT_TEXTURE1DARRAY}, - {"Texture2DArray", D3D_SVT_TEXTURE2DARRAY}, - {"RWTexture1DArray", D3D_SVT_RWTEXTURE1DARRAY}, - {"RWTexture2DArray", D3D_SVT_RWTEXTURE2DARRAY}, - {"Texture2DMSArray", D3D_SVT_TEXTURE2DMSARRAY}, - {"TextureCubeArray", D3D_SVT_TEXTURECUBEARRAY}, - {"SamplerState", D3D_SVT_SAMPLER}, - {"ByteAddressBuffer", D3D_SVT_BYTEADDRESS_BUFFER}, - {"RWByteAddressBuffer", D3D_SVT_RWBYTEADDRESS_BUFFER}, - {"StructuredBuffer", D3D_SVT_STRUCTURED_BUFFER}, - {"RWStructuredBuffer", D3D_SVT_RWSTRUCTURED_BUFFER}, - {"AppendStructuredBuffer", D3D_SVT_APPEND_STRUCTURED_BUFFER}, - {"ConsumeStructuredBuffer", D3D_SVT_CONSUME_STRUCTURED_BUFFER}, - {"RWBuffer", D3D_SVT_RWBUFFER}, - {"Buffer", D3D_SVT_BUFFER}, - {"ConstantBuffer", D3D_SVT_CBUFFER}}}; - - if (const TemplateSpecializationType *spec = - dyn_cast(display.getTypePtr())) { - - const TemplateDecl *td = spec->getTemplateName().getAsTemplateDecl(); - - if (td) { - - auto it = lookup.find(td->getName()); - - if (it != lookup.end()) { - - if(it->second >= 0) - displayName = underlyingName = it->first; - } - } - } - - bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - //Two arrays; for display and for underlying - - uint32_t arrayIdUnderlying = PushArray(Refl, arraySizeUnderlying, arrayElemUnderlying); - DxcHLSLArrayOrElements elementsOrArrayIdUnderlying(arrayIdUnderlying, arraySizeUnderlying); - - uint32_t arrayIdDisplay = PushArray(Refl, arraySizeDisplay, arrayElemDisplay); - DxcHLSLArrayOrElements elementsOrArrayIdDisplay(arrayIdDisplay, arraySizeDisplay); - - //Unwrap vector and matrix - //And base type - - D3D_SHADER_VARIABLE_CLASS cls = D3D_SVC_STRUCT; - - if (const RecordType *RT = underlying->getAs()) { - - const RecordDecl *RD = RT->getDecl(); - - if (RD->getTagKind() == TTK_Interface) - cls = D3D_SVC_INTERFACE_CLASS; - } - - uint8_t rows = 0, columns = 0; - - uint32_t membersCount = 0; - uint32_t membersOffset = 0; - - uint32_t baseType = uint32_t(-1); - std::vector interfaces; - - D3D_SHADER_VARIABLE_TYPE type = D3D_SVT_VOID; - - if (const RecordType *record = underlying->getAs()) { - - bool standardType = false; - - RecordDecl *recordDecl = record->getDecl(); - - QualType innerType; - std::string innerTypeName; //$Element or T depending on type - - if (const ClassTemplateSpecializationDecl *templateClass = - dyn_cast(recordDecl)) { - - std::string name = templateClass->getIdentifier()->getName(); - - const ArrayRef ¶ms = - templateClass->getTemplateArgs().asArray(); - - auto it = lookup.find(name); - - if (it != lookup.end()) { - - D3D_SHADER_VARIABLE_TYPE svt = it->second; - - if (svt == -1) { //Reserved as 'vector' - - rows = 1; - - assert(params.size() == 2 && - params[0].getKind() == TemplateArgument::Type && - params[1].getKind() == TemplateArgument::Integral && - "Expected vector to be vector"); - - underlying = params[0].getAsType(); - columns = params[1].getAsIntegral().getSExtValue(); - cls = D3D_SVC_VECTOR; - standardType = true; - } - - else if (svt == -2) { //Reserved as 'matrix' - - assert(params.size() == 3 && - params[0].getKind() == TemplateArgument::Type && - params[1].getKind() == TemplateArgument::Integral && - params[2].getKind() == TemplateArgument::Integral && - "Expected matrix to be matrix"); - - underlying = params[0].getAsType(); - columns = params[1].getAsIntegral().getSExtValue(); - rows = params[2].getAsIntegral().getSExtValue(); - - bool isRowMajor = DefaultRowMaj; - - HasHLSLMatOrientation(Original, &isRowMajor); - - if (!isRowMajor) - std::swap(rows, columns); - - cls = isRowMajor ? D3D_SVC_MATRIX_ROWS : D3D_SVC_MATRIX_COLUMNS; - standardType = true; - } - - else { - - type = svt; - cls = D3D_SVC_OBJECT; - - innerTypeName = "$Element"; - - const TemplateSpecializationType *templateDesc = - display->getAs(); - - assert(templateDesc && "Expected a valid TemplateSpecializationType"); - innerType = templateDesc->getArg(0).getAsType(); - - if (svt == D3D_SVT_RWBUFFER || svt == D3D_SVT_BUFFER || svt == D3D_SVT_CBUFFER) - innerTypeName = innerType.getUnqualifiedType().getAsString(policy); - } - } - } - - else { - - std::string name = recordDecl->getName(); - - auto it = lookup.find(name); - - if (it != lookup.end()) { - type = it->second; - cls = D3D_SVC_OBJECT; - } - } - - // Buffer types have a member to allow inspection of the types - - if (innerTypeName.size()) { - - uint32_t nameId = hasSymbols ? RegisterString(Refl, innerTypeName, false) - : uint32_t(-1); - - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, innerType, DefaultRowMaj); - - membersOffset = uint32_t(Refl.MemberTypeIds.size()); - membersCount = 1; - - Refl.MemberTypeIds.push_back(typeId); - - if (hasSymbols) - Refl.MemberNameIds.push_back(nameId); - } - - // Fill members - - if (!standardType && recordDecl->isCompleteDefinition() && cls != D3D_SVC_OBJECT) { - - // Base types - - if (CXXRecordDecl *cxxRecordDecl = dyn_cast(recordDecl)) - if (cxxRecordDecl->getNumBases()) { - for (auto &I : cxxRecordDecl->bases()) { - - QualType qualType = I.getType(); - CXXRecordDecl *BaseDecl = - cast(qualType->castAs()->getDecl()); - - if (BaseDecl->isInterface()) { - interfaces.push_back( - GenerateTypeInfo(ASTCtx, Refl, qualType, DefaultRowMaj)); - continue; - } - - assert(baseType == uint32_t(-1) && - "Multiple base types isn't supported in HLSL"); - - baseType = GenerateTypeInfo(ASTCtx, Refl, qualType, DefaultRowMaj); - } - } - - // Inner types - - // Reserve member names and types - - for (Decl *decl : recordDecl->decls()) { - - FieldDecl *fieldDecl = dyn_cast(decl); - - if (!fieldDecl) - continue; - - if (!membersCount) - membersOffset = uint32_t(Refl.MemberTypeIds.size()); - - std::string name = fieldDecl->getName(); - - uint32_t nameId = - hasSymbols ? RegisterString(Refl, name, false) : uint32_t(-1); - - if (hasSymbols) - Refl.MemberNameIds.push_back(nameId); - - ++membersCount; - } - - if (membersCount) { - - Refl.MemberTypeIds.resize(Refl.MemberTypeIds.size() + membersCount); - - if (Refl.MemberTypeIds.size() >= uint32_t(1u << 24)) - throw std::invalid_argument("Members out of bounds"); - } - - // Initialize member types (because it causes recursion) - - membersCount = 0; - - for (Decl *decl : recordDecl->decls()) { - - FieldDecl *fieldDecl = dyn_cast(decl); - - if (!fieldDecl) - continue; - - Refl.MemberTypeIds[membersOffset + membersCount] = - GenerateTypeInfo(ASTCtx, Refl, fieldDecl->getType(), DefaultRowMaj); - - ++membersCount; - } - } - } - - //Type name - - if (const BuiltinType *bt = dyn_cast(underlying)) { - - if (!rows) - rows = columns = 1; - - if (cls == D3D_SVC_STRUCT) - cls = D3D_SVC_SCALAR; - - switch (bt->getKind()) { - - case BuiltinType::Void: - type = D3D_SVT_VOID; - break; - - case BuiltinType::Min10Float: - type = D3D_SVT_MIN10FLOAT; - underlyingName = "min10float"; - break; - - case BuiltinType::Min16Float: - type = D3D_SVT_MIN16FLOAT; - underlyingName = "min16float"; - break; - - case BuiltinType::HalfFloat: - case BuiltinType::Half: - type = D3D_SVT_FLOAT16; - underlyingName = "float16_t"; //TODO: half or float16_t? - break; - - case BuiltinType::Short: - type = D3D_SVT_INT16; - underlyingName = "int16_t"; - break; - - case BuiltinType::Min12Int: - type = D3D_SVT_MIN12INT; - underlyingName = "min12int"; - break; - - case BuiltinType::Min16Int: - type = D3D_SVT_MIN16INT; - underlyingName = "min16int"; - break; - - case BuiltinType::Min16UInt: - type = D3D_SVT_MIN16UINT; - underlyingName = "min16uint"; - break; - - case BuiltinType::UShort: - type = D3D_SVT_UINT16; - underlyingName = "uint16_t"; - break; - - case BuiltinType::Float: - type = D3D_SVT_FLOAT; - underlyingName = "float"; - break; - - case BuiltinType::Int: - type = D3D_SVT_INT; - underlyingName = "int"; - break; - - case BuiltinType::UInt: - type = D3D_SVT_UINT; - underlyingName = "uint"; - break; - - case BuiltinType::Bool: - type = D3D_SVT_BOOL; - underlyingName = "bool"; - break; - - case BuiltinType::Double: - type = D3D_SVT_DOUBLE; - underlyingName = "double"; - break; - - case BuiltinType::ULongLong: - type = D3D_SVT_UINT64; - underlyingName = "uint64_t"; - break; - - case BuiltinType::LongLong: - type = D3D_SVT_INT64; - underlyingName = "int64_t"; - break; - - default: - throw std::invalid_argument("Invalid builtin type"); - } - } - - //Turn into proper fully qualified name (e.g. turn vector into float4) - - switch (cls) { - - case D3D_SVC_MATRIX_ROWS: - case D3D_SVC_VECTOR: - - underlyingName += std::to_string(columns); - - if (cls == D3D_SVC_MATRIX_ROWS) - underlyingName += "x" + std::to_string(rows); - - break; - - case D3D_SVC_MATRIX_COLUMNS: - underlyingName += std::to_string(rows) + "x" + std::to_string(columns); - break; - } - - //Insert - - if (Refl.Types.size() >= uint32_t(-1)) - throw std::invalid_argument("Type id out of bounds"); - - if (interfaces.size() >= uint8_t(-1)) - throw std::invalid_argument("Only allowing 256 interfaces"); - - uint32_t interfaceOffset = 0; - uint8_t interfaceCount = 0; - RegisterTypeList(Refl, interfaces, interfaceOffset, interfaceCount); - - DxcHLSLType hlslType(baseType, elementsOrArrayIdUnderlying, cls, type, rows, columns, - membersCount, membersOffset, interfaceOffset, - interfaceCount); - - uint32_t displayNameId = - hasSymbols ? RegisterString(Refl, displayName, false) : uint32_t(-1); - - uint32_t underlyingNameId = - hasSymbols ? RegisterString(Refl, underlyingName, false) : uint32_t(-1); - - DxcHLSLTypeSymbol typeSymbol(elementsOrArrayIdDisplay, displayNameId, - underlyingNameId); - - uint32_t i = 0; - uint32_t j = uint32_t(Refl.Types.size()); - - for (; i < j; ++i) - if (Refl.Types[i] == hlslType && - (!hasSymbols || Refl.TypeSymbols[i] == typeSymbol)) - break; - - if (i == j) { - - if (hasSymbols) - Refl.TypeSymbols.push_back(typeSymbol); - - Refl.Types.push_back(hlslType); - } - - return i; -} - -static D3D_CBUFFER_TYPE GetBufferType(uint8_t Type) { - - switch (Type) { - - case D3D_SIT_CBUFFER: - return D3D_CT_CBUFFER; - - case D3D_SIT_TBUFFER: - return D3D_CT_TBUFFER; - - case D3D_SIT_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED: - case D3D_SIT_UAV_APPEND_STRUCTURED: - case D3D_SIT_UAV_CONSUME_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: - return D3D_CT_RESOURCE_BIND_INFO; - - default: - return D3D_CT_INTERFACE_POINTERS; - } -} - -static void FillReflectionRegisterAt( - const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, - DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, - ValueDecl *ValDesc, const std::vector &ArraySize, - DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId, - bool DefaultRowMaj) { - - ArrayRef UA = ValDesc->getUnusualAnnotations(); - - DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); - - uint32_t nodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), - ValDesc, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, - uint32_t(Refl.Registers.size())); - - uint32_t arrayId = PushArray(Refl, ArraySizeFlat, ArraySize); - - uint32_t bufferId = 0; - D3D_CBUFFER_TYPE bufferType = GetBufferType(inputType.RegisterType); - - if(bufferType != D3D_CT_INTERFACE_POINTERS) { - bufferId = uint32_t(Refl.Buffers.size()); - Refl.Buffers.push_back({bufferType, nodeId}); - } - - DxcHLSLRegister regD3D12 = { - inputType.RegisterType, - ArraySizeFlat, - uint32_t(inputType.RegisterFlags), - inputType.TextureValue, - inputType.TextureDimension, - nodeId, - arrayId, - bufferId - }; - - Refl.Registers.push_back(regD3D12); - - bool isListType = true; - - switch (inputType.RegisterType) { - - case D3D_SIT_CBUFFER: - case D3D_SIT_TBUFFER: - isListType = false; - [[fallthrough]]; - - case D3D_SIT_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED: - case D3D_SIT_UAV_APPEND_STRUCTURED: - case D3D_SIT_UAV_CONSUME_STRUCTURED: - case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: { - - const TemplateSpecializationType *templateDesc = - Type->getAs(); - - assert(templateDesc->getNumArgs() == 1 && - templateDesc->getArg(0).getKind() == TemplateArgument::Type && - "Expected Type"); - - QualType innerType = templateDesc->getArg(0).getAsType(); - - // The name of the inner struct is $Element if 'array', otherwise equal to - // register name - - uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, innerType, DefaultRowMaj); - - SourceRange sourceRange = ValDesc->getSourceRange(); - - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), - isListType ? "$Element" : ValDesc->getName(), nullptr, - D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, typeId, &sourceRange); - - break; - } - } -} - -//TODO: Debug code -class PrintfStream : public llvm::raw_ostream { -public: - PrintfStream() { SetUnbuffered(); } - -private: - void write_impl(const char *Ptr, size_t Size) override { - printf("%.*s\n", (int)Size, Ptr); // Print the raw buffer directly - } - - uint64_t current_pos() const override { return 0; } -}; - -template -void RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, - DxcHLSLReflectionData &Refl, const T &Decls, - bool DefaultRowMaj, uint32_t ParentId) { - - for (Decl *decl : Decls) { - - ValueDecl *valDecl = dyn_cast(decl); - assert(valDecl && "Decl was expected to be a ValueDecl but wasn't"); - QualType original = valDecl->getType(); +namespace hlsl { + +uint32_t DxcHLSLReflectionData::RegisterString(const std::string &Name, + bool IsNonDebug) { - const std::string &name = valDecl->getName(); + if (Name.size() >= 32768) + throw std::invalid_argument("Strings are limited to 32767"); - uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); + if (IsNonDebug) { - uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, decl, - D3D12_HLSL_NODE_TYPE_VARIABLE, ParentId, typeId); + if (StringsNonDebug.size() >= uint32_t(-1)) + throw std::invalid_argument("Strings overflow"); - //Handle struct recursion + auto it = StringsToIdNonDebug.find(Name); - if (RecordDecl *recordDecl = dyn_cast(decl)) { + if (it != StringsToIdNonDebug.end()) + return it->second; - if (!recordDecl->isCompleteDefinition()) - continue; + uint32_t stringId = uint32_t(StringsNonDebug.size()); - RecurseBuffer(ASTCtx, SM, Refl, recordDecl->fields(), DefaultRowMaj, nodeId); - } + StringsNonDebug.push_back(Name); + StringsToIdNonDebug[Name] = stringId; + return stringId; } -} - -uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, - const SourceManager &SM, DeclContext *Buffer, - uint32_t NodeId, D3D_CBUFFER_TYPE Type, - bool DefaultRowMaj) { - - if (Refl.Buffers.size() >= uint32_t(-1)) - throw std::invalid_argument("Buffer id out of bounds"); - - uint32_t bufferId = uint32_t(Refl.Buffers.size()); - - RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), DefaultRowMaj, NodeId); - - Refl.Buffers.push_back({Type, NodeId}); - - return bufferId; -} - -//DxilInterpolationMode.cpp but a little bit cleaned up -static D3D_INTERPOLATION_MODE GetInterpolationMode(Decl *decl) { - - if (!decl) //Return type - return D3D_INTERPOLATION_UNDEFINED; - bool bNoInterpolation = decl->hasAttr(); - bool bLinear = decl->hasAttr(); - bool bNoperspective = decl->hasAttr(); - bool bCentroid = decl->hasAttr(); - bool bSample = decl->hasAttr(); - - uint8_t mask = uint8_t(bNoInterpolation) << 4; - mask |= uint8_t(bLinear) << 3; - mask |= uint8_t(bNoperspective) << 2; - mask |= uint8_t(bCentroid) << 1; - mask |= uint8_t(bSample); - - if (mask > 16) - return D3D_INTERPOLATION_UNDEFINED; - - static constexpr const D3D_INTERPOLATION_MODE modes[] = { - D3D_INTERPOLATION_UNDEFINED, - D3D_INTERPOLATION_LINEAR_SAMPLE, - D3D_INTERPOLATION_LINEAR_CENTROID, - D3D_INTERPOLATION_LINEAR_SAMPLE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, - D3D_INTERPOLATION_LINEAR, - D3D_INTERPOLATION_LINEAR_SAMPLE, - D3D_INTERPOLATION_LINEAR_CENTROID, - D3D_INTERPOLATION_LINEAR_SAMPLE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, - D3D_INTERPOLATION_CONSTANT - }; - - return modes[mask]; -} - -static void AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, - DxcHLSLReflectionData &Refl, - const SourceManager &SM, uint32_t ParentNodeId, - bool DefaultRowMaj) { - - PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); - - uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, Type, DefaultRowMaj); - - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), - Decl && dyn_cast(Decl) ? dyn_cast(Decl)->getName() - : "", - Decl, D3D12_HLSL_NODE_TYPE_PARAMETER, ParentNodeId, - uint32_t(Refl.Parameters.size())); - - D3D_INTERPOLATION_MODE interpolationMode = GetInterpolationMode(Decl); - D3D_PARAMETER_FLAGS flags = D3D_PF_NONE; - - if (Decl) { + if (Strings.size() >= uint32_t(-1)) + throw std::invalid_argument("Strings overflow"); - if (Decl->hasAttr()) - flags = D3D_PARAMETER_FLAGS(flags | D3D_PF_IN); + auto it = StringsToId.find(Name); - if (Decl->hasAttr()) - flags = D3D_PARAMETER_FLAGS(flags | D3D_PF_OUT); + if (it != StringsToId.end()) + return it->second; - if (Decl->hasAttr()) - flags = D3D_PARAMETER_FLAGS(flags | D3D_PF_IN | D3D_PF_OUT); - } + uint32_t stringId = uint32_t(Strings.size()); - Refl.Parameters.push_back( - DxcHLSLParameter{typeId, nodeId, uint8_t(interpolationMode), uint8_t(flags)}); + Strings.push_back(Name); + StringsToId[Name] = stringId; + return stringId; } -static void RecursiveReflectBody( - const Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, - const SourceManager &SM, DxcHLSLReflectionData &Refl, - uint32_t AutoBindingSpace, uint32_t Depth, - D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, - bool DefaultRowMaj, std::unordered_map &FwdDecls, - const LangOptions &LangOpts, bool SkipNextCompound = false); +uint32_t +DxcHLSLReflectionData::PushArray(uint32_t ArraySizeFlat, + const std::vector &ArraySize) { -static void GenerateStatement( - ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, - DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, - D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, - bool DefaultRowMaj, std::unordered_map &FwdDecls, - const LangOptions &LangOpts, D3D12_HLSL_NODE_TYPE Type, - const VarDecl *VarDecl, const Stmt *Body, const Stmt *Init, - const Stmt *Self, bool IfAndHasElse = false) { + if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) + return uint32_t(-1); - uint32_t loc = uint32_t(Refl.Statements.size()); + if (Arrays.size() >= uint32_t((1u << 31) - 1)) + throw std::invalid_argument("Arrays would overflow"); - const SourceRange &sourceRange = Self->getSourceRange(); + uint32_t arrayId = uint32_t(Arrays.size()); - uint32_t nodeId = PushNextNodeId(Refl, SM, LangOpts, "", nullptr, Type, - ParentNodeId, loc, &sourceRange, &FwdDecls); + uint32_t arrayCountStart = uint32_t(ArraySizes.size()); + uint32_t numArrayElements = std::min(size_t(32), ArraySize.size()); - Refl.Statements.push_back(DxcHLSLStatement()); + if (ArraySizes.size() + numArrayElements >= ((1u << 26) - 1)) + throw std::invalid_argument("Array elements would overflow"); - if (VarDecl) { + for (uint32_t i = 0; i < ArraySize.size() && i < 8; ++i) { - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, VarDecl->getType(), DefaultRowMaj); + uint32_t arraySize = ArraySize[i]; - const SourceRange &sourceRange = VarDecl->getSourceRange(); + // Flatten rest of array to at least keep consistent array elements + if (i == 31) + for (uint32_t j = i + 1; j < ArraySize.size(); ++j) + arraySize *= ArraySize[j]; - PushNextNodeId(Refl, SM, LangOpts, VarDecl->getName(), VarDecl, - D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, typeId, &sourceRange, - &FwdDecls); + ArraySizes.push_back(arraySize); } - uint32_t start = uint32_t(Refl.Nodes.size()); - - RecursiveReflectBody(Init, ASTCtx, Diags, SM, Refl, AutoBindingSpace, - Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls, - LangOpts, true); + DxcHLSLArray arr = {numArrayElements, arrayCountStart}; - Refl.Statements[loc] = - DxcHLSLStatement(nodeId, uint32_t(Refl.Nodes.size() - start), VarDecl, IfAndHasElse); + for (uint32_t i = 0; i < Arrays.size(); ++i) + if (Arrays[i] == arr) + return i; - RecursiveReflectBody(Body, ASTCtx, Diags, SM, Refl, AutoBindingSpace, - Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls, - LangOpts, true); + Arrays.push_back(arr); + return arrayId; } -static void RecursiveReflectBody( - const Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, - const SourceManager &SM, DxcHLSLReflectionData &Refl, - uint32_t AutoBindingSpace, uint32_t Depth, - D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, - bool DefaultRowMaj, std::unordered_map &FwdDecls, - const LangOptions &LangOpts, - bool SkipNextCompound) { +void DxcHLSLReflectionData::RegisterTypeList( + const std::vector &TypeIds, uint32_t &Offset, uint8_t &Len) { - if (!Statement) + if (TypeIds.empty()) return; - while (const AttributedStmt *AS = dyn_cast(Statement)) - Statement = AS->getSubStmt(); - - if (const IfStmt *If = dyn_cast(Statement)) - GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, - D3D12_HLSL_NODE_TYPE_IF, If->getConditionVariable(), - If->getElse(), If->getThen(), If, If->getElse()); - - else if (const ForStmt *For = dyn_cast(Statement)) - GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ParentNodeId, DefaultRowMaj, FwdDecls, - LangOpts, D3D12_HLSL_NODE_TYPE_FOR, - For->getConditionVariable(), For->getBody(), - For->getInit(), For); - - else if (const WhileStmt *While = dyn_cast(Statement)) - GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ParentNodeId, DefaultRowMaj, FwdDecls, - LangOpts, D3D12_HLSL_NODE_TYPE_WHILE, - While->getConditionVariable(), While->getBody(), - nullptr, While); - - else if (const SwitchStmt *Switch = dyn_cast(Statement)) - GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ParentNodeId, DefaultRowMaj, FwdDecls, - LangOpts, D3D12_HLSL_NODE_TYPE_SWITCH, - Switch->getConditionVariable(), Switch->getBody(), nullptr, - Switch); - - else if (const DoStmt *Do = dyn_cast(Statement)) { - - const SourceRange &sourceRange = Do->getSourceRange(); - - uint32_t scopeNode = - PushNextNodeId(Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_DO, - ParentNodeId, 0, &sourceRange, &FwdDecls); - - RecursiveReflectBody(Do->getBody(), ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, scopeNode, - DefaultRowMaj, FwdDecls, LangOpts, true); - } - - else if (const CompoundStmt *scope = dyn_cast(Statement)) { - - const SourceRange &sourceRange = scope->getSourceRange(); - - uint32_t scopeNode = SkipNextCompound ? ParentNodeId : PushNextNodeId( - Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_SCOPE, - ParentNodeId, 0, &sourceRange, &FwdDecls); - - for (const Stmt *child : scope->body()) - RecursiveReflectBody(child, ASTCtx, Diags, SM, Refl, AutoBindingSpace, - Depth + 1, Features, scopeNode, DefaultRowMaj, - FwdDecls, LangOpts); - } - - else if (const DeclStmt *DS = dyn_cast(Statement)) { - for (Decl *D : DS->decls()) { - if (VarDecl *varDecl = dyn_cast(D)) { - - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, varDecl->getType(), DefaultRowMaj); - - const SourceRange &sourceRange = varDecl->getSourceRange(); - - PushNextNodeId(Refl, SM, LangOpts, varDecl->getName(), varDecl, - D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId, - &sourceRange, &FwdDecls); - } - } - } -} - -static void -RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, - DiagnosticsEngine &Diags, const SourceManager &SM, - DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, - uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, - uint32_t ParentNodeId, bool DefaultRowMaj, - std::unordered_map &FwdDecls) { - - PrintfStream pfStream; - - PrintingPolicy printingPolicy(ASTCtx.getLangOpts()); - - printingPolicy.SuppressInitializers = true; - printingPolicy.AnonymousTagLocations = false; - printingPolicy.TerseOutput = - true; // No inheritance list, trailing semicolons, etc. - printingPolicy.PolishForDeclaration = true; // Makes it print as a decl - printingPolicy.SuppressSpecifiers = false; // Prints e.g. "static" or "inline" - printingPolicy.SuppressScope = true; - - // Traverse AST to grab reflection data - - //TODO: scopes (if/switch/for/empty scope) - - for (Decl *it : Ctx.decls()) { - - SourceLocation Loc = it->getLocation(); - if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) //TODO: We might want to include these for a more complete picture. - continue; - - if (isa(it)) //Skip parameters, already handled explicitly - continue; - - if (HLSLBufferDecl *CBuffer = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) - continue; - - // TODO: Add Depth > 0 for reflection if - // D3D12_HLSL_REFLECTION_FEATURE_SCOPES - - if (Depth != 0) - continue; - - uint32_t nodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), CBuffer->getName(), - CBuffer, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, - uint32_t(Refl.Registers.size())); - - uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, SM, CBuffer, nodeId, - D3D_CT_CBUFFER, DefaultRowMaj); - - DxcHLSLRegister regD3D12 = {D3D_SIT_CBUFFER, - 1, - uint32_t(D3D_SIF_USERPACKED), - D3D_RESOURCE_RETURN_TYPE(0), - D3D_SRV_DIMENSION_UNKNOWN, - nodeId, - uint32_t(-1), - bufferId}; - - Refl.Registers.push_back(regD3D12); - } - - else if (FunctionDecl *Func = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS)) - continue; - - if (Func->isImplicit()) - continue; - - const FunctionDecl *Definition = nullptr; - - uint32_t nodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), Func->getName(), Func, - D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, - uint32_t(Refl.Functions.size()), nullptr, &FwdDecls); - - if (nodeId == uint32_t(-1)) // Duplicate fwd definition - continue; - - bool hasDefinition = Func->hasBody(Definition); - DxcHLSLFunction func = {nodeId, Func->getNumParams(), - !Func->getReturnType().getTypePtr()->isVoidType(), - hasDefinition}; - - for (uint32_t i = 0; i < func.GetNumParameters(); ++i) - AddFunctionParameter(ASTCtx, Func->getParamDecl(i)->getType(), - Func->getParamDecl(i), Refl, SM, nodeId, - DefaultRowMaj); - - if (func.HasReturn()) - AddFunctionParameter(ASTCtx, Func->getReturnType(), nullptr, Refl, SM, - nodeId, DefaultRowMaj); - - Refl.Functions.push_back(std::move(func)); - - if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { - - Stmt *stmt = Func->getBody(); - - for (const Stmt *subStmt : stmt->children()) { - - if (!subStmt) - continue; - - RecursiveReflectBody(subStmt, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth, Features, nodeId, - DefaultRowMaj, FwdDecls, ASTCtx.getLangOpts()); - } - } - } - - else if (TypedefDecl *Typedef = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - uint32_t typeId = GenerateTypeInfo( - ASTCtx, Refl, Typedef->getUnderlyingType(), DefaultRowMaj); - - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), Typedef->getName(), - Typedef, D3D12_HLSL_NODE_TYPE_TYPEDEF, ParentNodeId, - typeId); - } - - else if (TypeAliasDecl *TypeAlias = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - // TODO: TypeAlias->print(pfStream, printingPolicy); - } - - else if (EnumDecl *Enum = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), Enum->getName(), Enum, - D3D12_HLSL_NODE_TYPE_ENUM, ParentNodeId, - uint32_t(Refl.Enums.size()), nullptr, &FwdDecls); - - if (nodeId == uint32_t(-1)) // Duplicate fwd definition - continue; - - for (EnumConstantDecl *EnumValue : Enum->enumerators()) { - - uint32_t childNodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), EnumValue->getName(), - EnumValue, D3D12_HLSL_NODE_TYPE_ENUM_VALUE, nodeId, - uint32_t(Refl.EnumValues.size())); - - Refl.EnumValues.push_back( - {EnumValue->getInitVal().getSExtValue(), childNodeId}); - } - - if (Refl.EnumValues.size() >= uint32_t(1 << 30)) - throw std::invalid_argument("Enum values overflow"); - - QualType enumType = Enum->getIntegerType(); - QualType desugared = enumType.getDesugaredType(ASTCtx); - const auto &semantics = ASTCtx.getTypeInfo(desugared); - - D3D12_HLSL_ENUM_TYPE type; - - switch (semantics.Width) { - - default: - case 32: - type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT - : D3D12_HLSL_ENUM_TYPE_INT; - break; - - case 16: - type = desugared->isUnsignedIntegerType() - ? D3D12_HLSL_ENUM_TYPE_UINT16_T - : D3D12_HLSL_ENUM_TYPE_INT16_T; - break; - - case 64: - type = desugared->isUnsignedIntegerType() - ? D3D12_HLSL_ENUM_TYPE_UINT64_T - : D3D12_HLSL_ENUM_TYPE_INT64_T; - break; - } - - Refl.Enums.push_back({nodeId, type}); - } - - else if (FieldDecl *fieldDecl = dyn_cast(it)) { - - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, fieldDecl->getType(), DefaultRowMaj); - - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), fieldDecl->getName(), - fieldDecl, D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, - typeId); - } - - else if (ValueDecl *ValDecl = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) - continue; - - VarDecl *varDecl = dyn_cast(it); - - if (varDecl && varDecl->hasAttr()) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - const std::string &name = ValDecl->getName(); - - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, ValDecl->getType(), DefaultRowMaj); - - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, - D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE, ParentNodeId, - typeId); - - continue; - } - - if (varDecl && varDecl->getStorageClass() == StorageClass::SC_Static) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - const std::string &name = ValDecl->getName(); - - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, ValDecl->getType(), DefaultRowMaj); - - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, - D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE, ParentNodeId, typeId); - - continue; - } - - uint32_t arraySize = 1; - QualType type = ValDecl->getType(); - std::vector arrayElem; - - while (const ConstantArrayType *arr = dyn_cast(type)) { - uint32_t current = arr->getSize().getZExtValue(); - arrayElem.push_back(current); - arraySize *= arr->getSize().getZExtValue(); - type = arr->getElementType(); - } - - if (!IsHLSLResourceType(type)) { - - // Handle $Globals - - if (varDecl && - (Depth == 0 || Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { - - const std::string &name = ValDecl->getName(); - - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, ValDecl->getType(), DefaultRowMaj); - - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, - D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId); - } - - continue; - } - - if (Depth != 0) - continue; - - FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, ValDecl, - arrayElem, Refl, AutoBindingSpace, ParentNodeId, - DefaultRowMaj); - } - - else if (RecordDecl *RecDecl = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - bool isDefinition = RecDecl->isThisDeclarationADefinition(); - - D3D12_HLSL_NODE_TYPE type = D3D12_HLSL_NODE_TYPE_RESERVED; - - switch (RecDecl->getTagKind()) { - - case TTK_Struct: - type = D3D12_HLSL_NODE_TYPE_STRUCT; - break; - - case TTK_Union: - type = D3D12_HLSL_NODE_TYPE_UNION; - break; + if (TypeIds.size() >= uint8_t(-1)) + throw std::invalid_argument("Only allowing 256 types in a type list"); - case TTK_Interface: - type = D3D12_HLSL_NODE_TYPE_INTERFACE; - break; - } + uint32_t i = 0; + uint32_t j = uint32_t(TypeList.size()); + uint32_t k = 0; - if (type != D3D12_HLSL_NODE_TYPE_RESERVED) { + Offset = 0; - uint32_t typeId = 0; + for (; i < j; ++i) { - if (isDefinition) - typeId = GenerateTypeInfo( - ASTCtx, Refl, RecDecl->getASTContext().getRecordType(RecDecl), - DefaultRowMaj); + if (k == TypeIds.size()) + break; - uint32_t self = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), RecDecl->getName(), RecDecl, type, - ParentNodeId, typeId, nullptr, &FwdDecls); + if (TypeIds[k] != TypeList[i]) { - if (self == uint32_t(-1)) // Duplicate fwd definition - continue; + if (k) + i = Offset; - if (isDefinition) - RecursiveReflectHLSL(*RecDecl, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, self, - DefaultRowMaj, FwdDecls); - } + k = 0; + break; } - else if (NamespaceDecl *Namespace = dyn_cast(it)) { - - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES)) - continue; - - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), Namespace->getName(), Namespace, - D3D12_HLSL_NODE_TYPE_NAMESPACE, ParentNodeId, 0); + if (!k) + Offset = i; - RecursiveReflectHLSL(*Namespace, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, nodeId, - DefaultRowMaj, FwdDecls); - } + ++k; } -} - -bool DxcHLSLReflectionData::Initialize(clang::CompilerInstance &Compiler, - clang::TranslationUnitDecl &Ctx, - uint32_t AutoBindingSpace, - D3D12_HLSL_REFLECTION_FEATURE Features, - bool DefaultRowMaj, - DxcHLSLReflectionData &Result) { - DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); - const SourceManager &SM = Compiler.getSourceManager(); - - Result = {}; - Result.Features = Features; + if (k != TypeIds.size()) { - if (Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { - Result.Strings.push_back(""); - Result.StringsToId[""] = 0; - Result.NodeSymbols.push_back(DxcHLSLNodeSymbol(0, 0, 0, 0, 0, 0)); - } + uint32_t oldSiz = uint32_t(TypeList.size()); - Result.Nodes.push_back(DxcHLSLNode{D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, - 0, 0, 0xFFFF, 0, uint16_t(-1)}); + if (oldSiz + TypeIds.size() >= (1u << 24)) + throw std::invalid_argument("Only allowing 16Mi total interfaces"); - try { + TypeList.resize(oldSiz + TypeIds.size()); - std::unordered_map fwdDecls; - RecursiveReflectHLSL(Ctx, Compiler.getASTContext(), Diags, SM, Result, - AutoBindingSpace, 0, Features, 0, DefaultRowMaj, - fwdDecls); - return true; + std::memcpy(TypeList.data() + oldSiz, TypeIds.data(), + TypeIds.size() * sizeof(uint32_t)); - } catch (const std::invalid_argument &arg) { - llvm::errs() << "DxcHLSLReflectionData::Initialize: Failed " << arg.what(); - return false; + Offset = oldSiz; } + + Len = uint8_t(TypeIds.size()); } //TODO: Debug print code @@ -2560,6 +881,28 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { TypeSymbols, Buffers, Parameters, Statements); } +D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { + + switch (Type) { + + case D3D_SIT_CBUFFER: + return D3D_CT_CBUFFER; + + case D3D_SIT_TBUFFER: + return D3D_CT_TBUFFER; + + case D3D_SIT_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: + return D3D_CT_RESOURCE_BIND_INFO; + + default: + return D3D_CT_INTERFACE_POINTERS; + } +} + DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes, bool MakeNameLookupTable) { @@ -3202,7 +1545,6 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes GenerateNameLookupTable(); } - void DxcHLSLReflectionData::Printf() const { RecursePrint(*this, 0, 0, 0); } -} +} // namespace hlsl diff --git a/tools/clang/tools/libclang/CMakeLists.txt b/tools/clang/tools/libclang/CMakeLists.txt index 28374eca80..f183e1ab17 100644 --- a/tools/clang/tools/libclang/CMakeLists.txt +++ b/tools/clang/tools/libclang/CMakeLists.txt @@ -31,6 +31,7 @@ set(SOURCES dxcisenseimpl.cpp # HLSL Change dxcrewriteunused.cpp # HLSL Change dxcreflector.cpp # HLSL Change + dxcreflection_from_ast.cpp # HLSL Change ADDITIONAL_HEADERS CIndexDiagnostic.h @@ -72,6 +73,7 @@ set(SOURCES dxcisenseimpl.cpp # HLSL Change dxcrewriteunused.cpp # HLSL Change dxcreflector.cpp # HLSL Change + dxcreflection_from_ast.cpp # HLSL Change ADDITIONAL_HEADERS CIndexDiagnostic.h diff --git a/tools/clang/tools/libclang/dxcreflection_from_ast.cpp b/tools/clang/tools/libclang/dxcreflection_from_ast.cpp new file mode 100644 index 0000000000..02f743f78b --- /dev/null +++ b/tools/clang/tools/libclang/dxcreflection_from_ast.cpp @@ -0,0 +1,1643 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// dxreflection_from_ast.cpp // +// Copyright (C) Microsoft Corporation. All rights reserved. // +// This file is distributed under the University of Illinois Open Source // +// License. See LICENSE.TXT for details. // +// // +// Handles walking the AST and turning it into a reflection object. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include "clang/AST/Attr.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/HlslTypes.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/basic/SourceManager.h" +#include "clang/Lex/Lexer.h" +#include "dxc/DxcReflection/DxcReflection.h" + +using namespace clang; + +namespace hlsl { + +static uint32_t +PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, + const LangOptions &LangOpts, const std::string &UnqualifiedName, + const Decl *DeclSelf, D3D12_HLSL_NODE_TYPE Type, + uint32_t ParentNodeId, uint32_t LocalId, + const SourceRange *Range = nullptr, + std::unordered_map *FwdDecls = nullptr) +{ + + if (Refl.Nodes.size() >= (1u << 24)) + throw std::invalid_argument("Nodes overflow"); + + if (LocalId >= (1u << 24)) + throw std::invalid_argument("LocalId overflow"); + + uint32_t nodeId = Refl.Nodes.size(); + + uint16_t annotationStart = uint16_t(Refl.Annotations.size()); + uint8_t annotationCount = 0; + + uint16_t semanticId = uint16_t(-1); + + if (DeclSelf) { + for (const Attr *attr : DeclSelf->attrs()) { + if (const AnnotateAttr *annotate = dyn_cast(attr)) { + + if (Refl.Annotations.size() >= (1u << 16)) + throw std::invalid_argument("Out of annotations"); + + Refl.Annotations.push_back(DxcHLSLAnnotation( + Refl.RegisterString(annotate->getAnnotation().str(), true), false)); + + if (annotationCount >= uint8_t(-1)) + throw std::invalid_argument("Annotation count out of bounds"); + + ++annotationCount; + + } else if (const HLSLShaderAttr *shaderAttr = + dyn_cast(attr)) { + + if (Refl.Annotations.size() >= (1u << 16)) + throw std::invalid_argument("Out of annotations"); + + Refl.Annotations.push_back(DxcHLSLAnnotation( + Refl.RegisterString( + "shader(\"" + shaderAttr->getStage().str() + "\")", true), + true)); + + if (annotationCount >= uint8_t(-1)) + throw std::invalid_argument("Annotation count out of bounds"); + + ++annotationCount; + + } + } + + if (const ValueDecl *valDecl = dyn_cast(DeclSelf)) { + + const ArrayRef &UA = + valDecl->getUnusualAnnotations(); + + for (auto It = UA.begin(), E = UA.end(); It != E; ++It) + if ((*It)->getKind() == hlsl::UnusualAnnotation::UA_SemanticDecl) { + semanticId = Refl.RegisterString( + cast(*It)->SemanticName.str(), true); + } + } + } + + bool isFwdDeclare = false; + bool canHaveFwdDeclare = false; + const Decl *fwdDeclare = nullptr; + + if (DeclSelf) { + + if (const FunctionDecl *func = dyn_cast(DeclSelf)) { + isFwdDeclare = !func->doesThisDeclarationHaveABody(); + fwdDeclare = func->getCanonicalDecl(); + canHaveFwdDeclare = true; + } + + else if (const EnumDecl *enm = dyn_cast(DeclSelf)) { + isFwdDeclare = !enm->isCompleteDefinition(); + fwdDeclare = enm->getCanonicalDecl(); + canHaveFwdDeclare = true; + } + + else if (const RecordDecl *rec = dyn_cast(DeclSelf)) { + + isFwdDeclare = !rec->isThisDeclarationADefinition(); + fwdDeclare = rec->getCanonicalDecl(); + canHaveFwdDeclare = true; + + if (isFwdDeclare && rec->isImplicit()) //Inner ghost node + return uint32_t(-1); + } + } + + uint32_t currId = uint32_t(Refl.Nodes.size()); + + if (canHaveFwdDeclare) { + + assert(FwdDecls && "Fwd decl requires FwdDecls map to be present"); + + // Multiple fwd declare, ignore + if (isFwdDeclare && FwdDecls->find(fwdDeclare) != FwdDecls->end()) + return uint32_t(-1); + + if (isFwdDeclare) + (*FwdDecls)[fwdDeclare] = currId; + } + + Refl.Nodes.push_back(DxcHLSLNode{Type, isFwdDeclare, LocalId, annotationStart, + 0, ParentNodeId, annotationCount, + semanticId}); + + if (Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { + + uint16_t sourceLineCount = 0; + uint32_t sourceLineStart = 0; + uint32_t sourceColumnStart = 0; + uint32_t sourceColumnEnd = 0; + + uint16_t sourceId = uint16_t(-1); + + SourceRange range = DeclSelf ? DeclSelf->getSourceRange() + : (Range ? *Range : SourceRange()); + + SourceLocation start = range.getBegin(); + SourceLocation end = range.getEnd(); + + if (start.isValid() && end.isValid()) { + + PresumedLoc presumed = SM.getPresumedLoc(start); + + SourceLocation realEnd = SM.getFileLoc(end); + SourceLocation endOfToken = + Lexer::getLocForEndOfToken(realEnd, 0, SM, LangOpts); + PresumedLoc presumedEnd = SM.getPresumedLoc(endOfToken); + + if (presumed.isValid() && presumedEnd.isValid()) { + + uint32_t startLine = presumed.getLine(); + uint32_t startCol = presumed.getColumn(); + uint32_t endLine = presumedEnd.getLine(); + uint32_t endCol = presumedEnd.getColumn(); + + std::string fileName = presumed.getFilename(); + + if (fileName != presumedEnd.getFilename()) + throw std::invalid_argument("End and start are not in the same file"); + + auto it = Refl.StringToSourceId.find(fileName); + uint32_t i; + + if (it == Refl.StringToSourceId.end()) { + i = (uint32_t)Refl.Sources.size(); + Refl.Sources.push_back(Refl.RegisterString(fileName, false)); + Refl.StringToSourceId[fileName] = i; + } + + else { + i = it->second; + } + + if (i >= 65535) + throw std::invalid_argument("Source file count is limited to 16-bit"); + + if ((endLine - startLine) >= 65535) + throw std::invalid_argument("Source line count is limited to 16-bit"); + + if (startLine >= 1048576) + throw std::invalid_argument("Source line start is limited to 20-bit"); + + if (startCol >= (1u << 22)) + throw std::invalid_argument("Column start is limited to 22-bit"); + + if (endCol >= (1u << 22)) + throw std::invalid_argument("Column end is limited to 22-bit"); + + sourceLineCount = uint16_t(endLine - startLine + 1); + sourceLineStart = startLine; + sourceColumnStart = startCol; + sourceColumnEnd = endCol; + sourceId = uint16_t(i); + } + } + + uint32_t nameId = Refl.RegisterString(UnqualifiedName, false); + + Refl.NodeSymbols.push_back( + DxcHLSLNodeSymbol(nameId, sourceId, sourceLineCount, sourceLineStart, + sourceColumnStart, sourceColumnEnd)); + } + + // Link + + if (DeclSelf && fwdDeclare != DeclSelf && fwdDeclare && !isFwdDeclare) { + assert(FwdDecls && "Referencing fwd decl requires FwdDecls map to be present"); + uint32_t fwd = (*FwdDecls)[fwdDeclare]; + Refl.Nodes[fwd].ResolveFwdDeclare(fwd, Refl.Nodes[currId], currId); + } + + uint32_t parentParent = ParentNodeId; + + while (parentParent != 0) { + DxcHLSLNode &parent = Refl.Nodes[parentParent]; + parent.IncreaseChildCount(); + parentParent = parent.GetParentId(); + } + + Refl.Nodes[0].IncreaseChildCount(); + + return nodeId; +} + +struct DxcRegisterTypeInfo { + D3D_SHADER_INPUT_TYPE RegisterType; + D3D_SHADER_INPUT_FLAGS RegisterFlags; + D3D_SRV_DIMENSION TextureDimension; + D3D_RESOURCE_RETURN_TYPE TextureValue; +}; + +static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, + std::string TypeName, + bool IsWrite, + const CXXRecordDecl *RecordDecl) { + + DxcRegisterTypeInfo type = {}; + type.RegisterType = IsWrite ? D3D_SIT_UAV_RWTYPED : D3D_SIT_TEXTURE; + + //Parse return type and dimensions + + const ClassTemplateSpecializationDecl *textureTemplate = + dyn_cast(RecordDecl); + + assert(textureTemplate && "Expected texture template"); + + const ArrayRef& textureParams = textureTemplate->getTemplateArgs().asArray(); + + bool shouldBeTexture2DMS = textureParams.size() == 2; + + if (shouldBeTexture2DMS) + assert(textureParams[0].getKind() == TemplateArgument::Type && + textureParams[1].getKind() == TemplateArgument::Integral && + "Expected template args"); + + else assert(textureParams.size() == 1 && + textureParams[0].getKind() == TemplateArgument::Type && + "Expected template args"); + + QualType valueType = textureParams[0].getAsType(); + QualType desugared = valueType.getDesugaredType(ASTCtx); + + uint32_t dimensions; + + if (const BuiltinType *bt = dyn_cast(desugared)) + dimensions = 1; + + else { + + const RecordType *RT = desugared->getAs(); + assert(RT && "Expected record type"); + + const CXXRecordDecl *RD = dyn_cast(RT->getDecl()); + assert(RT && "Expected record decl"); + + const ClassTemplateSpecializationDecl *vectorType = + dyn_cast(RD); + + assert(vectorType && + "Expected vector type as template inside of texture template"); + + const ArrayRef &vectorParams = + vectorType->getTemplateArgs().asArray(); + + assert(vectorParams.size() == 2 && + vectorParams[0].getKind() == TemplateArgument::Type && + vectorParams[1].getKind() == TemplateArgument::Integral && + "Expected vector to be vector"); + + valueType = vectorParams[0].getAsType(); + desugared = valueType.getDesugaredType(ASTCtx); + + dimensions = vectorParams[1].getAsIntegral().getZExtValue(); + } + + if (desugared->isFloatingType()) { + type.TextureValue = desugared->isSpecificBuiltinType(BuiltinType::Double) + ? D3D_RETURN_TYPE_DOUBLE + : D3D_RETURN_TYPE_FLOAT; + } else if (desugared->isIntegerType()) { + const auto &semantics = ASTCtx.getTypeInfo(desugared); + if (semantics.Width == 64) { + type.TextureValue = D3D_RETURN_TYPE_MIXED; + } else { + type.TextureValue = desugared->isUnsignedIntegerType() + ? D3D_RETURN_TYPE_UINT + : D3D_RETURN_TYPE_SINT; + } + } + + else { + type.TextureValue = D3D_RETURN_TYPE_MIXED; + } + + switch (dimensions) { + case 2: + type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENT_0; + break; + case 3: + type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENT_1; + break; + case 4: + type.RegisterFlags = (D3D_SHADER_INPUT_FLAGS)D3D_SIF_TEXTURE_COMPONENTS; + break; + } + + //Parse type + + if (TypeName == "Buffer") { + assert(!shouldBeTexture2DMS && "Buffer expected but got Buffer"); + type.TextureDimension = D3D_SRV_DIMENSION_BUFFER; + return type; + } + + bool isFeedback = false; + + if (TypeName.size() > 8 && TypeName.substr(0, 8) == "Feedback") { + isFeedback = true; + TypeName = TypeName.substr(8); + type.RegisterType = D3D_SIT_UAV_FEEDBACKTEXTURE; + } + + bool isArray = false; + + if (TypeName.size() > 5 && TypeName.substr(TypeName.size() - 5) == "Array") { + isArray = true; + TypeName = TypeName.substr(0, TypeName.size() - 5); + } + + if (TypeName == "Texture2D") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2D; + + else if (TypeName == "TextureCube") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURECUBE; + + else if (TypeName == "Texture3D") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE3D; + + else if (TypeName == "Texture1D") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE1D; + + else if (TypeName == "Texture2DMS") + type.TextureDimension = D3D_SRV_DIMENSION_TEXTURE2DMS; + + assert((shouldBeTexture2DMS == + (type.TextureDimension == D3D_SRV_DIMENSION_TEXTURE2DMS)) && + "Texture2DMS used with Texture2D syntax or reverse"); + + if (isArray) //Arrays are always 1 behind the regular type + type.TextureDimension = (D3D_SRV_DIMENSION)(type.TextureDimension + 1); + + return type; +} + +static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, + QualType Type) { + + QualType realType = Type.getDesugaredType(ASTCtx); + const RecordType *RT = realType->getAs(); + assert(RT && "GetRegisterTypeInfo() type is not a RecordType"); + + const CXXRecordDecl *recordDecl = RT->getAsCXXRecordDecl(); + assert(recordDecl && "GetRegisterTypeInfo() type is not a CXXRecordDecl"); + + std::string typeName = recordDecl->getNameAsString(); + + if (typeName.size() >= 17 && typeName.substr(0, 17) == "RasterizerOrdered") + typeName = typeName.substr(17); + + if (typeName == "SamplerState" || typeName == "SamplerComparisonState") { + return {D3D_SIT_SAMPLER, typeName == "SamplerComparisonState" + ? D3D_SIF_COMPARISON_SAMPLER + : (D3D_SHADER_INPUT_FLAGS)0}; + } + + DxcRegisterTypeInfo info = {}; + + if (typeName == "AppendStructuredBuffer") { + info.RegisterType = D3D_SIT_UAV_APPEND_STRUCTURED; + return info; + } + + if (typeName == "ConsumeStructuredBuffer") { + info.RegisterType = D3D_SIT_UAV_CONSUME_STRUCTURED; + return info; + } + + if (typeName == "RaytracingAccelerationStructure") { + info.RegisterType = D3D_SIT_RTACCELERATIONSTRUCTURE; + return info; + } + + if (typeName == "TextureBuffer") { + info.RegisterType = D3D_SIT_TBUFFER; + return info; + } + + if (typeName == "ConstantBuffer") { + info.RegisterType = D3D_SIT_CBUFFER; + return info; + } + + bool isWrite = + typeName.size() > 2 && typeName[0] == 'R' && typeName[1] == 'W'; + + if (isWrite) + typeName = typeName.substr(2); + + if (typeName == "StructuredBuffer") { + info.RegisterType = + isWrite ? D3D_SIT_UAV_RWSTRUCTURED : D3D_SIT_STRUCTURED; + return info; + } + + if (typeName == "ByteAddressBuffer") { + info.RegisterType = + isWrite ? D3D_SIT_UAV_RWBYTEADDRESS : D3D_SIT_BYTEADDRESS; + return info; + } + + return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); +} + +uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, + QualType Original, bool DefaultRowMaj) { + + // Unwrap array + // There's the following issue: + // Let's say the underlying type is F32x4[4] but the sugared name is F32x4x4, + // then we want to maintain sugared name + array info (of sugar) for reflection + // but for low level type info, we would want to know float4[4] + + uint32_t arraySizeUnderlying = 1; + QualType underlying = Original.getNonReferenceType().getCanonicalType(); + std::vector arrayElemUnderlying; + + while (const ConstantArrayType *arr = + dyn_cast(underlying)) { + uint32_t current = arr->getSize().getZExtValue(); + arrayElemUnderlying.push_back(current); + arraySizeUnderlying *= arr->getSize().getZExtValue(); + underlying = arr->getElementType().getNonReferenceType().getCanonicalType(); + } + + uint32_t arraySizeDisplay = 1; + std::vector arrayElemDisplay; + QualType display = Original.getNonReferenceType(); + + while (const ConstantArrayType *arr = dyn_cast(display)) { + uint32_t current = arr->getSize().getZExtValue(); + arrayElemDisplay.push_back(current); + arraySizeDisplay *= arr->getSize().getZExtValue(); + display = arr->getElementType().getNonReferenceType(); + } + + // Name; Omit struct, class and const keywords + + PrintingPolicy policy(ASTCtx.getLangOpts()); + policy.SuppressScope = false; + policy.AnonymousTagLocations = false; + policy.SuppressTagKeyword = true; + + display = display.getUnqualifiedType(); + std::string displayName = display.getAsString(policy); + + std::string underlyingName = + underlying.getUnqualifiedType().getAsString(policy); + + //Prune template instantiation from type name for builtin types (ex. vector & matrix) + //But only if it's not a sugared type: + // typedef ConstantBuffer MyTest; + //In this case, MyTest will still be seen as a ConstantBuffer but the typeName is MyTest. + + static const std::unordered_map + lookup = std::unordered_map{ + {{"vector", D3D_SHADER_VARIABLE_TYPE(-1)}, + {"matrix", D3D_SHADER_VARIABLE_TYPE(-2)}, + {"Texture1D", D3D_SVT_TEXTURE1D}, + {"Texture2D", D3D_SVT_TEXTURE2D}, + {"RWTexture1D", D3D_SVT_RWTEXTURE1D}, + {"RWTexture2D", D3D_SVT_RWTEXTURE2D}, + {"Texture2DMS", D3D_SVT_TEXTURE2DMS}, + {"Texture3D", D3D_SVT_TEXTURE3D}, + {"RWTexture3D", D3D_SVT_RWTEXTURE3D}, + {"TextureCube", D3D_SVT_TEXTURECUBE}, + {"Texture1DArray", D3D_SVT_TEXTURE1DARRAY}, + {"Texture2DArray", D3D_SVT_TEXTURE2DARRAY}, + {"RWTexture1DArray", D3D_SVT_RWTEXTURE1DARRAY}, + {"RWTexture2DArray", D3D_SVT_RWTEXTURE2DARRAY}, + {"Texture2DMSArray", D3D_SVT_TEXTURE2DMSARRAY}, + {"TextureCubeArray", D3D_SVT_TEXTURECUBEARRAY}, + {"SamplerState", D3D_SVT_SAMPLER}, + {"ByteAddressBuffer", D3D_SVT_BYTEADDRESS_BUFFER}, + {"RWByteAddressBuffer", D3D_SVT_RWBYTEADDRESS_BUFFER}, + {"StructuredBuffer", D3D_SVT_STRUCTURED_BUFFER}, + {"RWStructuredBuffer", D3D_SVT_RWSTRUCTURED_BUFFER}, + {"AppendStructuredBuffer", D3D_SVT_APPEND_STRUCTURED_BUFFER}, + {"ConsumeStructuredBuffer", D3D_SVT_CONSUME_STRUCTURED_BUFFER}, + {"RWBuffer", D3D_SVT_RWBUFFER}, + {"Buffer", D3D_SVT_BUFFER}, + {"ConstantBuffer", D3D_SVT_CBUFFER}}}; + + if (const TemplateSpecializationType *spec = + dyn_cast(display.getTypePtr())) { + + const TemplateDecl *td = spec->getTemplateName().getAsTemplateDecl(); + + if (td) { + + auto it = lookup.find(td->getName()); + + if (it != lookup.end()) { + + if(it->second >= 0) + displayName = underlyingName = it->first; + } + } + } + + bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + //Two arrays; for display and for underlying + + uint32_t arrayIdUnderlying = Refl.PushArray(arraySizeUnderlying, arrayElemUnderlying); + DxcHLSLArrayOrElements elementsOrArrayIdUnderlying(arrayIdUnderlying, arraySizeUnderlying); + + uint32_t arrayIdDisplay = Refl.PushArray(arraySizeDisplay, arrayElemDisplay); + DxcHLSLArrayOrElements elementsOrArrayIdDisplay(arrayIdDisplay, arraySizeDisplay); + + //Unwrap vector and matrix + //And base type + + D3D_SHADER_VARIABLE_CLASS cls = D3D_SVC_STRUCT; + + if (const RecordType *RT = underlying->getAs()) { + + const RecordDecl *RD = RT->getDecl(); + + if (RD->getTagKind() == TTK_Interface) + cls = D3D_SVC_INTERFACE_CLASS; + } + + uint8_t rows = 0, columns = 0; + + uint32_t membersCount = 0; + uint32_t membersOffset = 0; + + uint32_t baseType = uint32_t(-1); + std::vector interfaces; + + D3D_SHADER_VARIABLE_TYPE type = D3D_SVT_VOID; + + if (const RecordType *record = underlying->getAs()) { + + bool standardType = false; + + RecordDecl *recordDecl = record->getDecl(); + + QualType innerType; + std::string innerTypeName; //$Element or T depending on type + + if (const ClassTemplateSpecializationDecl *templateClass = + dyn_cast(recordDecl)) { + + std::string name = templateClass->getIdentifier()->getName(); + + const ArrayRef ¶ms = + templateClass->getTemplateArgs().asArray(); + + auto it = lookup.find(name); + + if (it != lookup.end()) { + + D3D_SHADER_VARIABLE_TYPE svt = it->second; + + if (svt == -1) { //Reserved as 'vector' + + rows = 1; + + assert(params.size() == 2 && + params[0].getKind() == TemplateArgument::Type && + params[1].getKind() == TemplateArgument::Integral && + "Expected vector to be vector"); + + underlying = params[0].getAsType(); + columns = params[1].getAsIntegral().getSExtValue(); + cls = D3D_SVC_VECTOR; + standardType = true; + } + + else if (svt == -2) { //Reserved as 'matrix' + + assert(params.size() == 3 && + params[0].getKind() == TemplateArgument::Type && + params[1].getKind() == TemplateArgument::Integral && + params[2].getKind() == TemplateArgument::Integral && + "Expected matrix to be matrix"); + + underlying = params[0].getAsType(); + columns = params[1].getAsIntegral().getSExtValue(); + rows = params[2].getAsIntegral().getSExtValue(); + + bool isRowMajor = DefaultRowMaj; + + HasHLSLMatOrientation(Original, &isRowMajor); + + if (!isRowMajor) + std::swap(rows, columns); + + cls = isRowMajor ? D3D_SVC_MATRIX_ROWS : D3D_SVC_MATRIX_COLUMNS; + standardType = true; + } + + else { + + type = svt; + cls = D3D_SVC_OBJECT; + + innerTypeName = "$Element"; + + const TemplateSpecializationType *templateDesc = + display->getAs(); + + assert(templateDesc && "Expected a valid TemplateSpecializationType"); + innerType = templateDesc->getArg(0).getAsType(); + + if (svt == D3D_SVT_RWBUFFER || svt == D3D_SVT_BUFFER || svt == D3D_SVT_CBUFFER) + innerTypeName = innerType.getUnqualifiedType().getAsString(policy); + } + } + } + + else { + + std::string name = recordDecl->getName(); + + auto it = lookup.find(name); + + if (it != lookup.end()) { + type = it->second; + cls = D3D_SVC_OBJECT; + } + } + + // Buffer types have a member to allow inspection of the types + + if (innerTypeName.size()) { + + uint32_t nameId = hasSymbols ? Refl.RegisterString(innerTypeName, false) + : uint32_t(-1); + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, innerType, DefaultRowMaj); + + membersOffset = uint32_t(Refl.MemberTypeIds.size()); + membersCount = 1; + + Refl.MemberTypeIds.push_back(typeId); + + if (hasSymbols) + Refl.MemberNameIds.push_back(nameId); + } + + // Fill members + + if (!standardType && recordDecl->isCompleteDefinition() && cls != D3D_SVC_OBJECT) { + + // Base types + + if (CXXRecordDecl *cxxRecordDecl = dyn_cast(recordDecl)) + if (cxxRecordDecl->getNumBases()) { + for (auto &I : cxxRecordDecl->bases()) { + + QualType qualType = I.getType(); + CXXRecordDecl *BaseDecl = + cast(qualType->castAs()->getDecl()); + + if (BaseDecl->isInterface()) { + interfaces.push_back( + GenerateTypeInfo(ASTCtx, Refl, qualType, DefaultRowMaj)); + continue; + } + + assert(baseType == uint32_t(-1) && + "Multiple base types isn't supported in HLSL"); + + baseType = GenerateTypeInfo(ASTCtx, Refl, qualType, DefaultRowMaj); + } + } + + // Inner types + + // Reserve member names and types + + for (Decl *decl : recordDecl->decls()) { + + FieldDecl *fieldDecl = dyn_cast(decl); + + if (!fieldDecl) + continue; + + if (!membersCount) + membersOffset = uint32_t(Refl.MemberTypeIds.size()); + + std::string name = fieldDecl->getName(); + + uint32_t nameId = + hasSymbols ? Refl.RegisterString(name, false) : uint32_t(-1); + + if (hasSymbols) + Refl.MemberNameIds.push_back(nameId); + + ++membersCount; + } + + if (membersCount) { + + Refl.MemberTypeIds.resize(Refl.MemberTypeIds.size() + membersCount); + + if (Refl.MemberTypeIds.size() >= uint32_t(1u << 24)) + throw std::invalid_argument("Members out of bounds"); + } + + // Initialize member types (because it causes recursion) + + membersCount = 0; + + for (Decl *decl : recordDecl->decls()) { + + FieldDecl *fieldDecl = dyn_cast(decl); + + if (!fieldDecl) + continue; + + Refl.MemberTypeIds[membersOffset + membersCount] = + GenerateTypeInfo(ASTCtx, Refl, fieldDecl->getType(), DefaultRowMaj); + + ++membersCount; + } + } + } + + //Type name + + if (const BuiltinType *bt = dyn_cast(underlying)) { + + if (!rows) + rows = columns = 1; + + if (cls == D3D_SVC_STRUCT) + cls = D3D_SVC_SCALAR; + + switch (bt->getKind()) { + + case BuiltinType::Void: + type = D3D_SVT_VOID; + break; + + case BuiltinType::Min10Float: + type = D3D_SVT_MIN10FLOAT; + underlyingName = "min10float"; + break; + + case BuiltinType::Min16Float: + type = D3D_SVT_MIN16FLOAT; + underlyingName = "min16float"; + break; + + case BuiltinType::HalfFloat: + case BuiltinType::Half: + type = D3D_SVT_FLOAT16; + underlyingName = "float16_t"; //TODO: half or float16_t? + break; + + case BuiltinType::Short: + type = D3D_SVT_INT16; + underlyingName = "int16_t"; + break; + + case BuiltinType::Min12Int: + type = D3D_SVT_MIN12INT; + underlyingName = "min12int"; + break; + + case BuiltinType::Min16Int: + type = D3D_SVT_MIN16INT; + underlyingName = "min16int"; + break; + + case BuiltinType::Min16UInt: + type = D3D_SVT_MIN16UINT; + underlyingName = "min16uint"; + break; + + case BuiltinType::UShort: + type = D3D_SVT_UINT16; + underlyingName = "uint16_t"; + break; + + case BuiltinType::Float: + type = D3D_SVT_FLOAT; + underlyingName = "float"; + break; + + case BuiltinType::Int: + type = D3D_SVT_INT; + underlyingName = "int"; + break; + + case BuiltinType::UInt: + type = D3D_SVT_UINT; + underlyingName = "uint"; + break; + + case BuiltinType::Bool: + type = D3D_SVT_BOOL; + underlyingName = "bool"; + break; + + case BuiltinType::Double: + type = D3D_SVT_DOUBLE; + underlyingName = "double"; + break; + + case BuiltinType::ULongLong: + type = D3D_SVT_UINT64; + underlyingName = "uint64_t"; + break; + + case BuiltinType::LongLong: + type = D3D_SVT_INT64; + underlyingName = "int64_t"; + break; + + default: + throw std::invalid_argument("Invalid builtin type"); + } + } + + //Turn into proper fully qualified name (e.g. turn vector into float4) + + switch (cls) { + + case D3D_SVC_MATRIX_ROWS: + case D3D_SVC_VECTOR: + + underlyingName += std::to_string(columns); + + if (cls == D3D_SVC_MATRIX_ROWS) + underlyingName += "x" + std::to_string(rows); + + break; + + case D3D_SVC_MATRIX_COLUMNS: + underlyingName += std::to_string(rows) + "x" + std::to_string(columns); + break; + } + + //Insert + + if (Refl.Types.size() >= uint32_t(-1)) + throw std::invalid_argument("Type id out of bounds"); + + if (interfaces.size() >= uint8_t(-1)) + throw std::invalid_argument("Only allowing 256 interfaces"); + + uint32_t interfaceOffset = 0; + uint8_t interfaceCount = 0; + Refl.RegisterTypeList(interfaces, interfaceOffset, interfaceCount); + + DxcHLSLType hlslType(baseType, elementsOrArrayIdUnderlying, cls, type, rows, columns, + membersCount, membersOffset, interfaceOffset, + interfaceCount); + + uint32_t displayNameId = + hasSymbols ? Refl.RegisterString(displayName, false) : uint32_t(-1); + + uint32_t underlyingNameId = + hasSymbols ? Refl.RegisterString(underlyingName, false) : uint32_t(-1); + + DxcHLSLTypeSymbol typeSymbol(elementsOrArrayIdDisplay, displayNameId, + underlyingNameId); + + uint32_t i = 0; + uint32_t j = uint32_t(Refl.Types.size()); + + for (; i < j; ++i) + if (Refl.Types[i] == hlslType && + (!hasSymbols || Refl.TypeSymbols[i] == typeSymbol)) + break; + + if (i == j) { + + if (hasSymbols) + Refl.TypeSymbols.push_back(typeSymbol); + + Refl.Types.push_back(hlslType); + } + + return i; +} + +static void FillReflectionRegisterAt( + const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, + DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, + ValueDecl *ValDesc, const std::vector &ArraySize, + DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId, + bool DefaultRowMaj) { + + ArrayRef UA = ValDesc->getUnusualAnnotations(); + + DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); + + uint32_t nodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), + ValDesc, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, + uint32_t(Refl.Registers.size())); + + uint32_t arrayId = Refl.PushArray(ArraySizeFlat, ArraySize); + + uint32_t bufferId = 0; + D3D_CBUFFER_TYPE bufferType = + DxcHLSLReflectionData::GetBufferType(inputType.RegisterType); + + if(bufferType != D3D_CT_INTERFACE_POINTERS) { + bufferId = uint32_t(Refl.Buffers.size()); + Refl.Buffers.push_back({bufferType, nodeId}); + } + + DxcHLSLRegister regD3D12 = { + inputType.RegisterType, + ArraySizeFlat, + uint32_t(inputType.RegisterFlags), + inputType.TextureValue, + inputType.TextureDimension, + nodeId, + arrayId, + bufferId + }; + + Refl.Registers.push_back(regD3D12); + + bool isListType = true; + + switch (inputType.RegisterType) { + + case D3D_SIT_CBUFFER: + case D3D_SIT_TBUFFER: + isListType = false; + [[fallthrough]]; + + case D3D_SIT_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: { + + const TemplateSpecializationType *templateDesc = + Type->getAs(); + + assert(templateDesc->getNumArgs() == 1 && + templateDesc->getArg(0).getKind() == TemplateArgument::Type && + "Expected Type"); + + QualType innerType = templateDesc->getArg(0).getAsType(); + + // The name of the inner struct is $Element if 'array', otherwise equal to + // register name + + uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, innerType, DefaultRowMaj); + + SourceRange sourceRange = ValDesc->getSourceRange(); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), + isListType ? "$Element" : ValDesc->getName(), nullptr, + D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, typeId, &sourceRange); + + break; + } + } +} + +template +void RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, + DxcHLSLReflectionData &Refl, const T &Decls, + bool DefaultRowMaj, uint32_t ParentId) { + + for (Decl *decl : Decls) { + + ValueDecl *valDecl = dyn_cast(decl); + assert(valDecl && "Decl was expected to be a ValueDecl but wasn't"); + QualType original = valDecl->getType(); + + const std::string &name = valDecl->getName(); + + uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); + + uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, decl, + D3D12_HLSL_NODE_TYPE_VARIABLE, ParentId, typeId); + + //Handle struct recursion + + if (RecordDecl *recordDecl = dyn_cast(decl)) { + + if (!recordDecl->isCompleteDefinition()) + continue; + + RecurseBuffer(ASTCtx, SM, Refl, recordDecl->fields(), DefaultRowMaj, nodeId); + } + } +} + +uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, + const SourceManager &SM, DeclContext *Buffer, + uint32_t NodeId, D3D_CBUFFER_TYPE Type, + bool DefaultRowMaj) { + + if (Refl.Buffers.size() >= uint32_t(-1)) + throw std::invalid_argument("Buffer id out of bounds"); + + uint32_t bufferId = uint32_t(Refl.Buffers.size()); + + RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), DefaultRowMaj, NodeId); + + Refl.Buffers.push_back({Type, NodeId}); + + return bufferId; +} + +//DxilInterpolationMode.cpp but a little bit cleaned up +static D3D_INTERPOLATION_MODE GetInterpolationMode(Decl *decl) { + + if (!decl) //Return type + return D3D_INTERPOLATION_UNDEFINED; + + bool bNoInterpolation = decl->hasAttr(); + bool bLinear = decl->hasAttr(); + bool bNoperspective = decl->hasAttr(); + bool bCentroid = decl->hasAttr(); + bool bSample = decl->hasAttr(); + + uint8_t mask = uint8_t(bNoInterpolation) << 4; + mask |= uint8_t(bLinear) << 3; + mask |= uint8_t(bNoperspective) << 2; + mask |= uint8_t(bCentroid) << 1; + mask |= uint8_t(bSample); + + if (mask > 16) + return D3D_INTERPOLATION_UNDEFINED; + + static constexpr const D3D_INTERPOLATION_MODE modes[] = { + D3D_INTERPOLATION_UNDEFINED, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_CENTROID, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_LINEAR, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_CENTROID, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_CONSTANT + }; + + return modes[mask]; +} + +static void AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, + DxcHLSLReflectionData &Refl, + const SourceManager &SM, uint32_t ParentNodeId, + bool DefaultRowMaj) { + + uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, Type, DefaultRowMaj); + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), + Decl && dyn_cast(Decl) ? dyn_cast(Decl)->getName() + : "", + Decl, D3D12_HLSL_NODE_TYPE_PARAMETER, ParentNodeId, + uint32_t(Refl.Parameters.size())); + + D3D_INTERPOLATION_MODE interpolationMode = GetInterpolationMode(Decl); + D3D_PARAMETER_FLAGS flags = D3D_PF_NONE; + + if (Decl) { + + if (Decl->hasAttr()) + flags = D3D_PARAMETER_FLAGS(flags | D3D_PF_IN); + + if (Decl->hasAttr()) + flags = D3D_PARAMETER_FLAGS(flags | D3D_PF_OUT); + + if (Decl->hasAttr()) + flags = D3D_PARAMETER_FLAGS(flags | D3D_PF_IN | D3D_PF_OUT); + } + + Refl.Parameters.push_back( + DxcHLSLParameter{typeId, nodeId, uint8_t(interpolationMode), uint8_t(flags)}); +} + +static void RecursiveReflectBody( + const Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, + const SourceManager &SM, DxcHLSLReflectionData &Refl, + uint32_t AutoBindingSpace, uint32_t Depth, + D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, + bool DefaultRowMaj, std::unordered_map &FwdDecls, + const LangOptions &LangOpts, bool SkipNextCompound = false); + +static void GenerateStatement( + ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, + DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, + D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, + bool DefaultRowMaj, std::unordered_map &FwdDecls, + const LangOptions &LangOpts, D3D12_HLSL_NODE_TYPE Type, + const VarDecl *VarDecl, const Stmt *Body, const Stmt *Init, + const Stmt *Self, bool IfAndHasElse = false) { + + uint32_t loc = uint32_t(Refl.Statements.size()); + + const SourceRange &sourceRange = Self->getSourceRange(); + + uint32_t nodeId = PushNextNodeId(Refl, SM, LangOpts, "", nullptr, Type, + ParentNodeId, loc, &sourceRange, &FwdDecls); + + Refl.Statements.push_back(DxcHLSLStatement()); + + if (VarDecl) { + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, VarDecl->getType(), DefaultRowMaj); + + const SourceRange &sourceRange = VarDecl->getSourceRange(); + + PushNextNodeId(Refl, SM, LangOpts, VarDecl->getName(), VarDecl, + D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, typeId, &sourceRange, + &FwdDecls); + } + + uint32_t start = uint32_t(Refl.Nodes.size()); + + RecursiveReflectBody(Init, ASTCtx, Diags, SM, Refl, AutoBindingSpace, + Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls, + LangOpts, true); + + Refl.Statements[loc] = + DxcHLSLStatement(nodeId, uint32_t(Refl.Nodes.size() - start), VarDecl, IfAndHasElse); + + RecursiveReflectBody(Body, ASTCtx, Diags, SM, Refl, AutoBindingSpace, + Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls, + LangOpts, true); +} + +static void RecursiveReflectBody( + const Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, + const SourceManager &SM, DxcHLSLReflectionData &Refl, + uint32_t AutoBindingSpace, uint32_t Depth, + D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, + bool DefaultRowMaj, std::unordered_map &FwdDecls, + const LangOptions &LangOpts, + bool SkipNextCompound) { + + if (!Statement) + return; + + while (const AttributedStmt *AS = dyn_cast(Statement)) + Statement = AS->getSubStmt(); + + if (const IfStmt *If = dyn_cast(Statement)) + GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, + D3D12_HLSL_NODE_TYPE_IF, If->getConditionVariable(), + If->getElse(), If->getThen(), If, If->getElse()); + + else if (const ForStmt *For = dyn_cast(Statement)) + GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, ParentNodeId, DefaultRowMaj, FwdDecls, + LangOpts, D3D12_HLSL_NODE_TYPE_FOR, + For->getConditionVariable(), For->getBody(), + For->getInit(), For); + + else if (const WhileStmt *While = dyn_cast(Statement)) + GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, ParentNodeId, DefaultRowMaj, FwdDecls, + LangOpts, D3D12_HLSL_NODE_TYPE_WHILE, + While->getConditionVariable(), While->getBody(), + nullptr, While); + + else if (const SwitchStmt *Switch = dyn_cast(Statement)) + GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, ParentNodeId, DefaultRowMaj, FwdDecls, + LangOpts, D3D12_HLSL_NODE_TYPE_SWITCH, + Switch->getConditionVariable(), Switch->getBody(), nullptr, + Switch); + + else if (const DoStmt *Do = dyn_cast(Statement)) { + + const SourceRange &sourceRange = Do->getSourceRange(); + + uint32_t scopeNode = + PushNextNodeId(Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_DO, + ParentNodeId, 0, &sourceRange, &FwdDecls); + + RecursiveReflectBody(Do->getBody(), ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, scopeNode, + DefaultRowMaj, FwdDecls, LangOpts, true); + } + + else if (const CompoundStmt *scope = dyn_cast(Statement)) { + + const SourceRange &sourceRange = scope->getSourceRange(); + + uint32_t scopeNode = SkipNextCompound ? ParentNodeId : PushNextNodeId( + Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_SCOPE, + ParentNodeId, 0, &sourceRange, &FwdDecls); + + for (const Stmt *child : scope->body()) + RecursiveReflectBody(child, ASTCtx, Diags, SM, Refl, AutoBindingSpace, + Depth + 1, Features, scopeNode, DefaultRowMaj, + FwdDecls, LangOpts); + } + + else if (const DeclStmt *DS = dyn_cast(Statement)) { + for (Decl *D : DS->decls()) { + if (VarDecl *varDecl = dyn_cast(D)) { + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, varDecl->getType(), DefaultRowMaj); + + const SourceRange &sourceRange = varDecl->getSourceRange(); + + PushNextNodeId(Refl, SM, LangOpts, varDecl->getName(), varDecl, + D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId, + &sourceRange, &FwdDecls); + } + } + } +} + +static void +RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, + DiagnosticsEngine &Diags, const SourceManager &SM, + DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, + uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, + uint32_t ParentNodeId, bool DefaultRowMaj, + std::unordered_map &FwdDecls) { + + // Traverse AST to grab reflection data + + for (Decl *it : Ctx.decls()) { + + SourceLocation Loc = it->getLocation(); + if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) //TODO: We might want to include these for a more complete picture. + continue; + + if (isa(it)) //Skip parameters, already handled explicitly + continue; + + if (HLSLBufferDecl *cbuffer = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) + continue; + + if (Depth != 0) + continue; + + uint32_t nodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), cbuffer->getName(), + cbuffer, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, + uint32_t(Refl.Registers.size())); + + uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, SM, cbuffer, nodeId, + D3D_CT_CBUFFER, DefaultRowMaj); + + DxcHLSLRegister regD3D12 = {D3D_SIT_CBUFFER, + 1, + uint32_t(D3D_SIF_USERPACKED), + D3D_RESOURCE_RETURN_TYPE(0), + D3D_SRV_DIMENSION_UNKNOWN, + nodeId, + uint32_t(-1), + bufferId}; + + Refl.Registers.push_back(regD3D12); + } + + else if (FunctionDecl *funcDecl = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS)) + continue; + + if (funcDecl->isImplicit()) //Skip ctors, etc. + continue; + + const FunctionDecl *definition = nullptr; + + uint32_t nodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), funcDecl->getName(), funcDecl, + D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, + uint32_t(Refl.Functions.size()), nullptr, &FwdDecls); + + if (nodeId == uint32_t(-1)) // Duplicate fwd definition + continue; + + bool hasDefinition = funcDecl->hasBody(definition); + DxcHLSLFunction func = {nodeId, funcDecl->getNumParams(), + !funcDecl->getReturnType().getTypePtr()->isVoidType(), + hasDefinition}; + + for (uint32_t i = 0; i < func.GetNumParameters(); ++i) + AddFunctionParameter(ASTCtx, funcDecl->getParamDecl(i)->getType(), + funcDecl->getParamDecl(i), Refl, SM, nodeId, + DefaultRowMaj); + + if (func.HasReturn()) + AddFunctionParameter(ASTCtx, funcDecl->getReturnType(), nullptr, Refl, SM, + nodeId, DefaultRowMaj); + + Refl.Functions.push_back(std::move(func)); + + if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { + + Stmt *stmt = funcDecl->getBody(); + + for (const Stmt *subStmt : stmt->children()) { + + if (!subStmt) + continue; + + RecursiveReflectBody(subStmt, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth, Features, nodeId, + DefaultRowMaj, FwdDecls, ASTCtx.getLangOpts()); + } + } + } + + else if (TypedefDecl *typedefDecl = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + uint32_t typeId = GenerateTypeInfo( + ASTCtx, Refl, typedefDecl->getUnderlyingType(), DefaultRowMaj); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), typedefDecl->getName(), + typedefDecl, D3D12_HLSL_NODE_TYPE_TYPEDEF, ParentNodeId, + typeId); + } + + else if (TypeAliasDecl *typeAlias = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + // TODO: Implement. typeAlias->print(pfStream, printingPolicy); + } + + else if (EnumDecl *enumDecl = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), enumDecl->getName(), enumDecl, + D3D12_HLSL_NODE_TYPE_ENUM, ParentNodeId, + uint32_t(Refl.Enums.size()), nullptr, &FwdDecls); + + if (nodeId == uint32_t(-1)) // Duplicate fwd definition + continue; + + for (EnumConstantDecl *enumValue : enumDecl->enumerators()) { + + uint32_t childNodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), enumValue->getName(), + enumValue, D3D12_HLSL_NODE_TYPE_ENUM_VALUE, nodeId, + uint32_t(Refl.EnumValues.size())); + + Refl.EnumValues.push_back( + {enumValue->getInitVal().getSExtValue(), childNodeId}); + } + + if (Refl.EnumValues.size() >= uint32_t(1 << 30)) + throw std::invalid_argument("Enum values overflow"); + + QualType enumType = enumDecl->getIntegerType(); + QualType desugared = enumType.getDesugaredType(ASTCtx); + const auto &semantics = ASTCtx.getTypeInfo(desugared); + + D3D12_HLSL_ENUM_TYPE type; + + switch (semantics.Width) { + + default: + case 32: + type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT + : D3D12_HLSL_ENUM_TYPE_INT; + break; + + case 16: + type = desugared->isUnsignedIntegerType() + ? D3D12_HLSL_ENUM_TYPE_UINT16_T + : D3D12_HLSL_ENUM_TYPE_INT16_T; + break; + + case 64: + type = desugared->isUnsignedIntegerType() + ? D3D12_HLSL_ENUM_TYPE_UINT64_T + : D3D12_HLSL_ENUM_TYPE_INT64_T; + break; + } + + Refl.Enums.push_back({nodeId, type}); + } + + else if (FieldDecl *fieldDecl = dyn_cast(it)) { + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, fieldDecl->getType(), DefaultRowMaj); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), fieldDecl->getName(), + fieldDecl, D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, + typeId); + } + + else if (ValueDecl *valDecl = dyn_cast(it)) { + + VarDecl *varDecl = dyn_cast(it); + + if (varDecl && varDecl->hasAttr()) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + const std::string &name = valDecl->getName(); + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, valDecl->getType(), DefaultRowMaj); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, + D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE, ParentNodeId, + typeId); + + continue; + } + + if (varDecl && varDecl->getStorageClass() == StorageClass::SC_Static) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + const std::string &name = valDecl->getName(); + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, valDecl->getType(), DefaultRowMaj); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, + D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE, ParentNodeId, typeId); + + continue; + } + + uint32_t arraySize = 1; + QualType type = valDecl->getType(); + std::vector arrayElem; + + while (const ConstantArrayType *arr = dyn_cast(type)) { + uint32_t current = arr->getSize().getZExtValue(); + arrayElem.push_back(current); + arraySize *= arr->getSize().getZExtValue(); + type = arr->getElementType(); + } + + if (!IsHLSLResourceType(type)) { + + // Handle $Globals + + if (varDecl && + (Depth == 0 || Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { + + const std::string &name = valDecl->getName(); + + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, valDecl->getType(), DefaultRowMaj); + + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, + D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId); + } + + continue; + } + + if (Depth != 0) + continue; + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) + continue; + + FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, valDecl, + arrayElem, Refl, AutoBindingSpace, ParentNodeId, + DefaultRowMaj); + } + + else if (RecordDecl *recDecl = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + continue; + + bool isDefinition = recDecl->isThisDeclarationADefinition(); + + D3D12_HLSL_NODE_TYPE type = D3D12_HLSL_NODE_TYPE_RESERVED; + + switch (recDecl->getTagKind()) { + + case TTK_Struct: + type = D3D12_HLSL_NODE_TYPE_STRUCT; + break; + + case TTK_Union: + type = D3D12_HLSL_NODE_TYPE_UNION; + break; + + case TTK_Interface: + type = D3D12_HLSL_NODE_TYPE_INTERFACE; + break; + } + + if (type != D3D12_HLSL_NODE_TYPE_RESERVED) { + + uint32_t typeId = 0; + + if (isDefinition) + typeId = GenerateTypeInfo( + ASTCtx, Refl, recDecl->getASTContext().getRecordType(recDecl), + DefaultRowMaj); + + uint32_t self = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), recDecl->getName(), recDecl, type, + ParentNodeId, typeId, nullptr, &FwdDecls); + + if (self == uint32_t(-1)) // Duplicate fwd definition + continue; + + if (isDefinition) + RecursiveReflectHLSL(*recDecl, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, self, + DefaultRowMaj, FwdDecls); + } + } + + else if (NamespaceDecl *Namespace = dyn_cast(it)) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES)) + continue; + + uint32_t nodeId = PushNextNodeId( + Refl, SM, ASTCtx.getLangOpts(), Namespace->getName(), Namespace, + D3D12_HLSL_NODE_TYPE_NAMESPACE, ParentNodeId, 0); + + RecursiveReflectHLSL(*Namespace, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, nodeId, + DefaultRowMaj, FwdDecls); + } + } +} + +bool DxcHLSLReflectionDataFromAST(DxcHLSLReflectionData &Result, + CompilerInstance &Compiler, + TranslationUnitDecl &Ctx, + uint32_t AutoBindingSpace, + D3D12_HLSL_REFLECTION_FEATURE Features, + bool DefaultRowMaj) { + + DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); + const SourceManager &SM = Compiler.getSourceManager(); + + Result = {}; + Result.Features = Features; + + if (Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { + Result.Strings.push_back(""); + Result.StringsToId[""] = 0; + Result.NodeSymbols.push_back(DxcHLSLNodeSymbol(0, 0, 0, 0, 0, 0)); + } + + Result.Nodes.push_back(DxcHLSLNode{D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, + 0, 0, 0xFFFF, 0, uint16_t(-1)}); + + try { + + std::unordered_map fwdDecls; + RecursiveReflectHLSL(Ctx, Compiler.getASTContext(), Diags, SM, Result, + AutoBindingSpace, 0, Features, 0, DefaultRowMaj, + fwdDecls); + return true; + + } catch (const std::invalid_argument &arg) { + llvm::errs() << "DxcHLSLReflectionData::Initialize: Failed " << arg.what(); + return false; + } +} + +} // namespace hlsl diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 8aaa4670cc..992313c551 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -49,6 +49,16 @@ using namespace llvm; using namespace clang; using namespace hlsl; +namespace hlsl { + +bool DxcHLSLReflectionDataFromAST(DxcHLSLReflectionData &Result, + clang::CompilerInstance &Compiler, + clang::TranslationUnitDecl &Ctx, + uint32_t AutoBindingSpace, + D3D12_HLSL_REFLECTION_FEATURE Features, + bool DefaultRowMaj); +} + struct ASTHelper { CompilerInstance compiler; TranslationUnitDecl *tu; @@ -1583,8 +1593,9 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, DxcHLSLReflectionData refl; - if (!refl.Initialize(astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, - reflectMask, opts.DefaultRowMajor, refl)) + if (!DxcHLSLReflectionDataFromAST(refl, astHelper.compiler, *astHelper.tu, + opts.AutoBindingSpace, reflectMask, + opts.DefaultRowMajor)) throw std::exception("refl.Initialize failed"); //TODO: Debug From 34f0f5f29135948e8b003fa3f695c4063230afa4 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 25 Oct 2025 23:05:08 +0200 Subject: [PATCH 063/126] Changed from a long if chain to a visitor pattern to be cleaner, faster and align better to clang/llvm --- .../tools/libclang/dxcreflection_from_ast.cpp | 417 +++++++++--------- 1 file changed, 219 insertions(+), 198 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflection_from_ast.cpp b/tools/clang/tools/libclang/dxcreflection_from_ast.cpp index 02f743f78b..50020e2722 100644 --- a/tools/clang/tools/libclang/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/libclang/dxcreflection_from_ast.cpp @@ -13,6 +13,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ASTContext.h" #include "clang/AST/HlslTypes.h" +#include "clang/AST/DeclVisitor.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/basic/SourceManager.h" #include "clang/Lex/Lexer.h" @@ -1284,132 +1285,149 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, - std::unordered_map &FwdDecls) { + std::unordered_map &FwdDecls); + +class RecursiveReflector : public DeclVisitor { + + const DeclContext &Ctx; + ASTContext &ASTCtx; + const SourceManager &SM; + DiagnosticsEngine &Diags; + DxcHLSLReflectionData &Refl; + uint32_t AutoBindingSpace; + uint32_t Depth; + D3D12_HLSL_REFLECTION_FEATURE Features; + uint32_t ParentNodeId; + bool DefaultRowMaj; + std::unordered_map &FwdDecls; + + void PushVariable(ValueDecl *VD, D3D12_HLSL_NODE_TYPE NodeType) { - // Traverse AST to grab reflection data + uint32_t typeId = + GenerateTypeInfo(ASTCtx, Refl, VD->getType(), DefaultRowMaj); - for (Decl *it : Ctx.decls()) { + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), VD->getName(), VD, NodeType, + ParentNodeId, typeId); + } - SourceLocation Loc = it->getLocation(); - if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) //TODO: We might want to include these for a more complete picture. - continue; +public: - if (isa(it)) //Skip parameters, already handled explicitly - continue; + RecursiveReflector(const DeclContext &Ctx, ASTContext &ASTCtx, + const SourceManager &SM, DiagnosticsEngine &Diags, + DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, + uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, + uint32_t ParentNodeId, bool DefaultRowMaj, + std::unordered_map &FwdDecls) + : Ctx(Ctx), ASTCtx(ASTCtx), Diags(Diags), SM(SM), Refl(Refl), + AutoBindingSpace(AutoBindingSpace), Depth(Depth), Features(Features), + ParentNodeId(ParentNodeId), DefaultRowMaj(DefaultRowMaj), + FwdDecls(FwdDecls){} - if (HLSLBufferDecl *cbuffer = dyn_cast(it)) { + void TraverseDeclContext() { - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) - continue; + for (Decl *it : Ctx.decls()) { - if (Depth != 0) + SourceLocation Loc = it->getLocation(); + if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) //TODO: We might want to include these for a more complete picture. continue; - uint32_t nodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), cbuffer->getName(), - cbuffer, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, - uint32_t(Refl.Registers.size())); - - uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, SM, cbuffer, nodeId, - D3D_CT_CBUFFER, DefaultRowMaj); - - DxcHLSLRegister regD3D12 = {D3D_SIT_CBUFFER, - 1, - uint32_t(D3D_SIF_USERPACKED), - D3D_RESOURCE_RETURN_TYPE(0), - D3D_SRV_DIMENSION_UNKNOWN, - nodeId, - uint32_t(-1), - bufferId}; - - Refl.Registers.push_back(regD3D12); + Visit(it); } + } - else if (FunctionDecl *funcDecl = dyn_cast(it)) { + void VisitDecl(Decl *D) {} - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS)) - continue; + void VisitHLSLBufferDecl(HLSLBufferDecl *CB) { - if (funcDecl->isImplicit()) //Skip ctors, etc. - continue; + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) + return; - const FunctionDecl *definition = nullptr; + if (Depth != 0) + return; - uint32_t nodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), funcDecl->getName(), funcDecl, - D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, - uint32_t(Refl.Functions.size()), nullptr, &FwdDecls); + uint32_t nodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), CB->getName(), CB, + D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, + uint32_t(Refl.Registers.size())); - if (nodeId == uint32_t(-1)) // Duplicate fwd definition - continue; + uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, SM, CB, nodeId, + D3D_CT_CBUFFER, DefaultRowMaj); - bool hasDefinition = funcDecl->hasBody(definition); - DxcHLSLFunction func = {nodeId, funcDecl->getNumParams(), - !funcDecl->getReturnType().getTypePtr()->isVoidType(), - hasDefinition}; + DxcHLSLRegister regD3D12 = {D3D_SIT_CBUFFER, + 1, + uint32_t(D3D_SIF_USERPACKED), + D3D_RESOURCE_RETURN_TYPE(0), + D3D_SRV_DIMENSION_UNKNOWN, + nodeId, + uint32_t(-1), + bufferId}; - for (uint32_t i = 0; i < func.GetNumParameters(); ++i) - AddFunctionParameter(ASTCtx, funcDecl->getParamDecl(i)->getType(), - funcDecl->getParamDecl(i), Refl, SM, nodeId, - DefaultRowMaj); + Refl.Registers.push_back(regD3D12); + } - if (func.HasReturn()) - AddFunctionParameter(ASTCtx, funcDecl->getReturnType(), nullptr, Refl, SM, - nodeId, DefaultRowMaj); + void VisitFunctionDecl(FunctionDecl *FD) { - Refl.Functions.push_back(std::move(func)); + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS)) + return; - if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { + if (FD->isImplicit()) // Skip ctors, etc. + return; - Stmt *stmt = funcDecl->getBody(); + const FunctionDecl *definition = nullptr; - for (const Stmt *subStmt : stmt->children()) { + uint32_t nodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), FD->getName(), FD, + D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, + uint32_t(Refl.Functions.size()), nullptr, &FwdDecls); - if (!subStmt) - continue; + if (nodeId == uint32_t(-1)) // Duplicate fwd definition + return; - RecursiveReflectBody(subStmt, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth, Features, nodeId, - DefaultRowMaj, FwdDecls, ASTCtx.getLangOpts()); - } - } - } + bool hasDefinition = FD->hasBody(definition); + DxcHLSLFunction func = {nodeId, FD->getNumParams(), + !FD->getReturnType().getTypePtr()->isVoidType(), + hasDefinition}; - else if (TypedefDecl *typedefDecl = dyn_cast(it)) { + for (uint32_t i = 0; i < func.GetNumParameters(); ++i) + AddFunctionParameter(ASTCtx, FD->getParamDecl(i)->getType(), + FD->getParamDecl(i), Refl, SM, nodeId, + DefaultRowMaj); - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; + if (func.HasReturn()) + AddFunctionParameter(ASTCtx, FD->getReturnType(), nullptr, Refl, SM, + nodeId, DefaultRowMaj); - uint32_t typeId = GenerateTypeInfo( - ASTCtx, Refl, typedefDecl->getUnderlyingType(), DefaultRowMaj); + Refl.Functions.push_back(std::move(func)); - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), typedefDecl->getName(), - typedefDecl, D3D12_HLSL_NODE_TYPE_TYPEDEF, ParentNodeId, - typeId); - } + if (hasDefinition && (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { - else if (TypeAliasDecl *typeAlias = dyn_cast(it)) { + Stmt *stmt = FD->getBody(); - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; + for (const Stmt *subStmt : stmt->children()) { + + if (!subStmt) + continue; - // TODO: Implement. typeAlias->print(pfStream, printingPolicy); + RecursiveReflectBody(subStmt, ASTCtx, Diags, SM, Refl, AutoBindingSpace, + Depth, Features, nodeId, DefaultRowMaj, FwdDecls, + ASTCtx.getLangOpts()); + } } + } - else if (EnumDecl *enumDecl = dyn_cast(it)) { + void VisitEnumDecl(EnumDecl *ED) { if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; + return; - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), enumDecl->getName(), enumDecl, + uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), ED->getName(), ED, D3D12_HLSL_NODE_TYPE_ENUM, ParentNodeId, uint32_t(Refl.Enums.size()), nullptr, &FwdDecls); if (nodeId == uint32_t(-1)) // Duplicate fwd definition - continue; + return; - for (EnumConstantDecl *enumValue : enumDecl->enumerators()) { + for (EnumConstantDecl *enumValue : ED->enumerators()) { uint32_t childNodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), enumValue->getName(), @@ -1423,7 +1441,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (Refl.EnumValues.size() >= uint32_t(1 << 30)) throw std::invalid_argument("Enum values overflow"); - QualType enumType = enumDecl->getIntegerType(); + QualType enumType = ED->getIntegerType(); QualType desugared = enumType.getDesugaredType(ASTCtx); const auto &semantics = ASTCtx.getTypeInfo(desugared); @@ -1451,157 +1469,160 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, } Refl.Enums.push_back({nodeId, type}); - } - - else if (FieldDecl *fieldDecl = dyn_cast(it)) { - - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, fieldDecl->getType(), DefaultRowMaj); - - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), fieldDecl->getName(), - fieldDecl, D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, - typeId); - } - - else if (ValueDecl *valDecl = dyn_cast(it)) { - - VarDecl *varDecl = dyn_cast(it); - - if (varDecl && varDecl->hasAttr()) { + } - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; - - const std::string &name = valDecl->getName(); + void VisitTypedefDecl(TypedefDecl *TD) { - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, valDecl->getType(), DefaultRowMaj); + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + return; - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, - D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE, ParentNodeId, - typeId); + uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, TD->getUnderlyingType(), + DefaultRowMaj); - continue; - } + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), TD->getName(), TD, + D3D12_HLSL_NODE_TYPE_TYPEDEF, ParentNodeId, typeId); + } + + void VisitFieldDecl(FieldDecl *FD) { + PushVariable(FD, D3D12_HLSL_NODE_TYPE_VARIABLE); + } - if (varDecl && varDecl->getStorageClass() == StorageClass::SC_Static) { + void VisitValueDecl(ValueDecl *VD) { - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; + if (isa(VD)) // Skip parameters, already handled explicitly + return; - const std::string &name = valDecl->getName(); + VarDecl *varDecl = dyn_cast(VD); + + if (varDecl && varDecl->hasAttr()) { - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, valDecl->getType(), DefaultRowMaj); + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + return; - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, - D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE, ParentNodeId, typeId); + PushVariable(VD, D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE); + return; + } + + if (varDecl && varDecl->getStorageClass() == StorageClass::SC_Static) { + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + return; + + PushVariable(VD, D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE); + return; + } + + uint32_t arraySize = 1; + QualType type = VD->getType(); + std::vector arrayElem; + + while (const ConstantArrayType *arr = dyn_cast(type)) { + uint32_t current = arr->getSize().getZExtValue(); + arrayElem.push_back(current); + arraySize *= arr->getSize().getZExtValue(); + type = arr->getElementType(); + } + + if (!IsHLSLResourceType(type)) { - continue; - } + // Handle $Globals or regular variables - uint32_t arraySize = 1; - QualType type = valDecl->getType(); - std::vector arrayElem; + if (varDecl && + (Depth == 0 || Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { - while (const ConstantArrayType *arr = dyn_cast(type)) { - uint32_t current = arr->getSize().getZExtValue(); - arrayElem.push_back(current); - arraySize *= arr->getSize().getZExtValue(); - type = arr->getElementType(); + PushVariable(VD, D3D12_HLSL_NODE_TYPE_VARIABLE); } - if (!IsHLSLResourceType(type)) { - - // Handle $Globals + return; + } + + if (Depth != 0 || !(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) + return; + + FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, VD, + arrayElem, Refl, AutoBindingSpace, ParentNodeId, + DefaultRowMaj); + } - if (varDecl && - (Depth == 0 || Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { + void VisitRecordDecl(RecordDecl *RD) { - const std::string &name = valDecl->getName(); + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + return; - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, valDecl->getType(), DefaultRowMaj); + bool isDefinition = RD->isThisDeclarationADefinition(); - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, it, - D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId); - } + D3D12_HLSL_NODE_TYPE type = D3D12_HLSL_NODE_TYPE_RESERVED; - continue; - } + switch (RD->getTagKind()) { - if (Depth != 0) - continue; + case TTK_Struct: + type = D3D12_HLSL_NODE_TYPE_STRUCT; + break; - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) - continue; + case TTK_Union: + type = D3D12_HLSL_NODE_TYPE_UNION; + break; - FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, valDecl, - arrayElem, Refl, AutoBindingSpace, ParentNodeId, - DefaultRowMaj); + case TTK_Interface: + type = D3D12_HLSL_NODE_TYPE_INTERFACE; + break; } - else if (RecordDecl *recDecl = dyn_cast(it)) { + if (type != D3D12_HLSL_NODE_TYPE_RESERVED) { - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - continue; + uint32_t typeId = 0; - bool isDefinition = recDecl->isThisDeclarationADefinition(); + if (isDefinition) + typeId = GenerateTypeInfo( + ASTCtx, Refl, RD->getASTContext().getRecordType(RD), DefaultRowMaj); - D3D12_HLSL_NODE_TYPE type = D3D12_HLSL_NODE_TYPE_RESERVED; + uint32_t self = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), RD->getName(), RD, + type, ParentNodeId, typeId, nullptr, &FwdDecls); - switch (recDecl->getTagKind()) { + if (self == uint32_t(-1)) // Duplicate fwd definition + return; - case TTK_Struct: - type = D3D12_HLSL_NODE_TYPE_STRUCT; - break; - - case TTK_Union: - type = D3D12_HLSL_NODE_TYPE_UNION; - break; - - case TTK_Interface: - type = D3D12_HLSL_NODE_TYPE_INTERFACE; - break; - } - - if (type != D3D12_HLSL_NODE_TYPE_RESERVED) { + if (isDefinition) + RecursiveReflectHLSL(*RD, ASTCtx, Diags, SM, Refl, AutoBindingSpace, + Depth + 1, Features, self, DefaultRowMaj, + FwdDecls); + } + } - uint32_t typeId = 0; + void VisitNamespaceDecl(NamespaceDecl *ND) { - if (isDefinition) - typeId = GenerateTypeInfo( - ASTCtx, Refl, recDecl->getASTContext().getRecordType(recDecl), - DefaultRowMaj); + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES)) + return; - uint32_t self = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), recDecl->getName(), recDecl, type, - ParentNodeId, typeId, nullptr, &FwdDecls); + uint32_t nodeId = + PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), ND->getName(), ND, + D3D12_HLSL_NODE_TYPE_NAMESPACE, ParentNodeId, 0); - if (self == uint32_t(-1)) // Duplicate fwd definition - continue; + RecursiveReflectHLSL(*ND, ASTCtx, Diags, SM, Refl, AutoBindingSpace, + Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls); + } - if (isDefinition) - RecursiveReflectHLSL(*recDecl, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, self, - DefaultRowMaj, FwdDecls); - } - } + /*void VisitTypeAliasDecl(TypeAliasDecl *TAD) { - else if (NamespaceDecl *Namespace = dyn_cast(it)) { + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + return; - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES)) - continue; + // TODO: Implement. TAD->print(pfStream, printingPolicy); + }*/ +}; - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), Namespace->getName(), Namespace, - D3D12_HLSL_NODE_TYPE_NAMESPACE, ParentNodeId, 0); +static void +RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, + DiagnosticsEngine &Diags, const SourceManager &SM, + DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, + uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, + uint32_t ParentNodeId, bool DefaultRowMaj, + std::unordered_map &FwdDecls) { - RecursiveReflectHLSL(*Namespace, ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, nodeId, - DefaultRowMaj, FwdDecls); - } - } + RecursiveReflector Reflector(Ctx, ASTCtx, SM, Diags, Refl, AutoBindingSpace, Depth, + Features, ParentNodeId, DefaultRowMaj, FwdDecls); + Reflector.TraverseDeclContext(); } bool DxcHLSLReflectionDataFromAST(DxcHLSLReflectionData &Result, From 0f66dce21b20f63dd4b3d7b7574a7dbd4bb454e4 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 26 Oct 2025 21:25:19 +0100 Subject: [PATCH 064/126] Moved Stmt traversal into a visitor StmtVisitor pattern --- .../tools/libclang/dxcreflection_from_ast.cpp | 130 ++++++++++++------ 1 file changed, 87 insertions(+), 43 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflection_from_ast.cpp b/tools/clang/tools/libclang/dxcreflection_from_ast.cpp index 50020e2722..ee0ae688fd 100644 --- a/tools/clang/tools/libclang/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/libclang/dxcreflection_from_ast.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/HlslTypes.h" #include "clang/AST/DeclVisitor.h" +#include "clang/AST/StmtVisitor.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/basic/SourceManager.h" #include "clang/Lex/Lexer.h" @@ -1142,7 +1143,7 @@ static void AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, } static void RecursiveReflectBody( - const Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, + Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, @@ -1155,8 +1156,8 @@ static void GenerateStatement( D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls, const LangOptions &LangOpts, D3D12_HLSL_NODE_TYPE Type, - const VarDecl *VarDecl, const Stmt *Body, const Stmt *Init, - const Stmt *Self, bool IfAndHasElse = false) { + const VarDecl *VarDecl, Stmt *Body, Stmt *Init, + Stmt *Self, bool IfAndHasElse = false) { uint32_t loc = uint32_t(Refl.Statements.size()); @@ -1193,50 +1194,68 @@ static void GenerateStatement( LangOpts, true); } -static void RecursiveReflectBody( - const Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, - const SourceManager &SM, DxcHLSLReflectionData &Refl, - uint32_t AutoBindingSpace, uint32_t Depth, - D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, - bool DefaultRowMaj, std::unordered_map &FwdDecls, - const LangOptions &LangOpts, - bool SkipNextCompound) { +struct RecursiveStmtReflector : public StmtVisitor { + + ASTContext &ASTCtx; + DiagnosticsEngine &Diags; + const SourceManager &SM; + DxcHLSLReflectionData &Refl; + uint32_t AutoBindingSpace; + uint32_t Depth; + D3D12_HLSL_REFLECTION_FEATURE Features; + uint32_t ParentNodeId; + bool DefaultRowMaj; + std::unordered_map &FwdDecls; + const LangOptions &LangOpts; + bool SkipNextCompound; + + RecursiveStmtReflector(ASTContext &ASTCtx, DiagnosticsEngine &Diags, + const SourceManager &SM, DxcHLSLReflectionData &Refl, + uint32_t AutoBindingSpace, uint32_t Depth, + D3D12_HLSL_REFLECTION_FEATURE Features, + uint32_t ParentNodeId, bool DefaultRowMaj, + std::unordered_map &FwdDecls, + const LangOptions &LangOpts, bool SkipNextCompound) + : ASTCtx(ASTCtx), Diags(Diags), SM(SM), Refl(Refl), + AutoBindingSpace(AutoBindingSpace), Depth(Depth), Features(Features), + ParentNodeId(ParentNodeId), DefaultRowMaj(DefaultRowMaj), + FwdDecls(FwdDecls), LangOpts(LangOpts), SkipNextCompound(SkipNextCompound) {} + + void TraverseStmt(Stmt *S) { - if (!Statement) - return; + if (!S) + return; - while (const AttributedStmt *AS = dyn_cast(Statement)) - Statement = AS->getSubStmt(); + while (AttributedStmt *AS = dyn_cast(S)) + S = AS->getSubStmt(); + + Visit(S); + } - if (const IfStmt *If = dyn_cast(Statement)) + void VisitStmt(const Stmt *S) {} + + void VisitIfStmt(IfStmt *If) { GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, D3D12_HLSL_NODE_TYPE_IF, If->getConditionVariable(), If->getElse(), If->getThen(), If, If->getElse()); + } - else if (const ForStmt *For = dyn_cast(Statement)) - GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ParentNodeId, DefaultRowMaj, FwdDecls, - LangOpts, D3D12_HLSL_NODE_TYPE_FOR, - For->getConditionVariable(), For->getBody(), - For->getInit(), For); - - else if (const WhileStmt *While = dyn_cast(Statement)) + void VisitForStmt(ForStmt *For) { GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ParentNodeId, DefaultRowMaj, FwdDecls, - LangOpts, D3D12_HLSL_NODE_TYPE_WHILE, - While->getConditionVariable(), While->getBody(), - nullptr, While); + Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, + D3D12_HLSL_NODE_TYPE_FOR, For->getConditionVariable(), + For->getBody(), For->getInit(), For); + } - else if (const SwitchStmt *Switch = dyn_cast(Statement)) + void VisitWhileStmt(WhileStmt *While) { GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ParentNodeId, DefaultRowMaj, FwdDecls, - LangOpts, D3D12_HLSL_NODE_TYPE_SWITCH, - Switch->getConditionVariable(), Switch->getBody(), nullptr, - Switch); - - else if (const DoStmt *Do = dyn_cast(Statement)) { + Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, + D3D12_HLSL_NODE_TYPE_WHILE, While->getConditionVariable(), + While->getBody(), nullptr, While); + } + void VisitDoStmt(DoStmt *Do) { const SourceRange &sourceRange = Do->getSourceRange(); uint32_t scopeNode = @@ -1248,21 +1267,32 @@ static void RecursiveReflectBody( DefaultRowMaj, FwdDecls, LangOpts, true); } - else if (const CompoundStmt *scope = dyn_cast(Statement)) { + void VisitSwitchStmt(SwitchStmt *Switch) { + GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, + D3D12_HLSL_NODE_TYPE_SWITCH, + Switch->getConditionVariable(), Switch->getBody(), + nullptr, Switch); + } + + void VisitCompoundStmt(CompoundStmt *C) { - const SourceRange &sourceRange = scope->getSourceRange(); + const SourceRange &sourceRange = C->getSourceRange(); - uint32_t scopeNode = SkipNextCompound ? ParentNodeId : PushNextNodeId( - Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_SCOPE, - ParentNodeId, 0, &sourceRange, &FwdDecls); + uint32_t scopeNode = + SkipNextCompound + ? ParentNodeId + : PushNextNodeId(Refl, SM, LangOpts, "", nullptr, + D3D12_HLSL_NODE_TYPE_SCOPE, ParentNodeId, 0, + &sourceRange, &FwdDecls); - for (const Stmt *child : scope->body()) + for (Stmt *child : C->body()) RecursiveReflectBody(child, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, scopeNode, DefaultRowMaj, FwdDecls, LangOpts); } - else if (const DeclStmt *DS = dyn_cast(Statement)) { + void VisitDeclStmt(DeclStmt *DS) { for (Decl *D : DS->decls()) { if (VarDecl *varDecl = dyn_cast(D)) { @@ -1277,6 +1307,20 @@ static void RecursiveReflectBody( } } } +}; + +static void +RecursiveReflectBody(Stmt *Statement, ASTContext &ASTCtx, + DiagnosticsEngine &Diags, const SourceManager &SM, + DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, + uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, + uint32_t ParentNodeId, bool DefaultRowMaj, + std::unordered_map &FwdDecls, + const LangOptions &LangOpts, bool SkipNextCompound) { + RecursiveStmtReflector Reflector(ASTCtx, Diags, SM, Refl, AutoBindingSpace, + Depth, Features, ParentNodeId, DefaultRowMaj, + FwdDecls, LangOpts, SkipNextCompound); + Reflector.TraverseStmt(Statement); } static void @@ -1403,7 +1447,7 @@ class RecursiveReflector : public DeclVisitor { Stmt *stmt = FD->getBody(); - for (const Stmt *subStmt : stmt->children()) { + for (Stmt *subStmt : stmt->children()) { if (!subStmt) continue; From 844c79ed39512632e5a73572cb74490024dc854c Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 29 Oct 2025 23:30:36 +0100 Subject: [PATCH 065/126] Changed exceptions to DxcReflectionError which is just a const char* made through returning DXC_REFLECT_ERR. Almost got all places. --- include/dxc/DxcReflection/DxcReflection.h | 306 +++++-- .../tools/dxcreflection/DxcReflection.cpp | 160 ++-- .../tools/libclang/dxcreflection_from_ast.cpp | 819 ++++++++++++------ tools/clang/tools/libclang/dxcreflector.cpp | 88 +- 4 files changed, 908 insertions(+), 465 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 26bae8f513..57e6d53854 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -22,6 +22,24 @@ namespace hlsl { +typedef const char *DxcReflectionError; +static constexpr const DxcReflectionError DxcReflectionSuccess = nullptr; + +#ifndef NDEBUG + #if defined(_MSC_VER) + #define DXC_FUNC_NAME __FUNCTION__ + #elif defined(__clang__) || defined(__GNUC__) + #define DXC_FUNC_NAME __PRETTY_FUNCTION__ + #else + #define DXC_FUNC_NAME __func__ + #endif + #define DXC_REFLECT_STRING(x) #x + #define DXC_REFLECT_STRING2(x) DXC_REFLECT_STRING(x) + #define DXC_REFLECT_ERR(x) (x " at " __FILE__ ":" DXC_REFLECT_STRING2(__LINE__) " (" DXC_FUNC_NAME ")") +#else + #define DXC_REFLECT_ERR(x) x +#endif + class DxcHLSLNode { uint32_t LocalIdParentLo; //24 : 8 @@ -53,42 +71,55 @@ class DxcHLSLNode { ChildCountFwdBckLo &= 0xFFFFFF; ChildCountFwdBckLo |= v << 24; } + + DxcHLSLNode(D3D12_HLSL_NODE_TYPE NodeType, + bool IsFwdDeclare, + uint32_t LocalId, uint16_t AnnotationStart, uint32_t ChildCount, + uint32_t ParentId, uint8_t AnnotationCount, uint16_t SemanticId) + : LocalIdParentLo(LocalId | (ParentId << 24)), ParentHi(ParentId >> 8), + Annotations(AnnotationCount), Type(NodeType), + ChildCountFwdBckLo(ChildCount | (0xFFu << 24)), FwdBckHi(0xFFFF), + AnnotationStart(AnnotationStart), SemanticId(SemanticId), Padding(0) { + + if (IsFwdDeclare) + Type |= 0x80; + } public: DxcHLSLNode() = default; - DxcHLSLNode(D3D12_HLSL_NODE_TYPE NodeType, bool IsFwdDeclare, + [[nodiscard]] static DxcReflectionError + Initialize(DxcHLSLNode &OutNode, D3D12_HLSL_NODE_TYPE NodeType, + bool IsFwdDeclare, uint32_t LocalId, uint16_t AnnotationStart, uint32_t ChildCount, - uint32_t ParentId, uint8_t AnnotationCount, uint16_t SemanticId) - : LocalIdParentLo(LocalId | (ParentId << 24)), ParentHi(ParentId >> 8), - Annotations(AnnotationCount), Type(NodeType), - ChildCountFwdBckLo(ChildCount | (0xFFu << 24)), FwdBckHi(0xFFFF), - AnnotationStart(AnnotationStart), SemanticId(SemanticId), Padding(0) { + uint32_t ParentId, uint8_t AnnotationCount, uint16_t SemanticId) { if (NodeType < D3D12_HLSL_NODE_TYPE_START || NodeType > D3D12_HLSL_NODE_TYPE_END) - throw std::invalid_argument("Invalid NodeType"); + return DXC_REFLECT_ERR("Invalid NodeType"); if (LocalId >= ((1u << 24) - 1)) - throw std::invalid_argument("LocalId out of bounds"); + return DXC_REFLECT_ERR("LocalId out of bounds"); if (ParentId >= ((1u << 24) - 1)) - throw std::invalid_argument("ParentId out of bounds"); + return DXC_REFLECT_ERR("ParentId out of bounds"); if (ChildCount >= ((1u << 24) - 1)) - throw std::invalid_argument("ChildCount out of bounds"); + return DXC_REFLECT_ERR("ChildCount out of bounds"); if (IsFwdDeclare) { if (AnnotationCount) - throw std::invalid_argument("Fwd declares aren't allowed to have annotations"); + return DXC_REFLECT_ERR("Fwd declares aren't allowed to have annotations"); if (ChildCount) - throw std::invalid_argument("Fwd declares aren't allowed to have children"); - - Type |= 0x80; + return DXC_REFLECT_ERR("Fwd declares aren't allowed to have children"); } + + OutNode = DxcHLSLNode(NodeType, IsFwdDeclare, LocalId, AnnotationStart, + ChildCount, ParentId, AnnotationCount, SemanticId); + return DxcReflectionSuccess; } bool IsFwdDeclare() const { return Type >> 7; } @@ -117,14 +148,15 @@ class DxcHLSLNode { bool IsFwdBckDefined() const { return GetFwdBck() != ((1 << 24) - 1); } - void ResolveFwdDeclare(uint32_t SelfId, DxcHLSLNode &Definition, - uint32_t DefinitionId) { + [[nodiscard]] DxcReflectionError ResolveFwdDeclare(uint32_t SelfId, + DxcHLSLNode &Definition, + uint32_t DefinitionId) { if (SelfId >= ((1u << 24) - 1)) - throw std::invalid_argument("SelfId out of bounds"); + return DXC_REFLECT_ERR("SelfId out of bounds"); if (DefinitionId >= ((1u << 24) - 1)) - throw std::invalid_argument("DefinitionId out of bounds"); + return DXC_REFLECT_ERR("DefinitionId out of bounds"); assert(DefinitionId != SelfId && "NodeId can't be definition id!"); assert(IsFwdDeclare() && @@ -135,6 +167,8 @@ class DxcHLSLNode { SetFwdBck(DefinitionId); Definition.SetFwdBck(SelfId); + + return DxcReflectionSuccess; } // For example if Enum, maps into Enums[LocalId] @@ -158,12 +192,13 @@ class DxcHLSLNode { return uint32_t(LocalIdParentLo >> 24) | (uint32_t(ParentHi) << 8); } - void IncreaseChildCount() { + [[nodiscard]] DxcReflectionError IncreaseChildCount() { if (GetChildCount() >= ((1u << 24) - 1)) - throw std::invalid_argument("Child count out of bounds"); + return DXC_REFLECT_ERR("Child count out of bounds"); ++ChildCountFwdBckLo; + return DxcReflectionSuccess; } bool operator==(const DxcHLSLNode &other) const { @@ -173,10 +208,9 @@ class DxcHLSLNode { AnnotationStartFwdBckHi == other.AnnotationStartFwdBckHi && SemanticId == other.SemanticId; } - }; -struct DxcHLSLNodeSymbol { +class DxcHLSLNodeSymbol { union { struct { @@ -196,9 +230,7 @@ struct DxcHLSLNodeSymbol { }; uint64_t SourceColumnStartEndLo; }; - - DxcHLSLNodeSymbol() = default; - + DxcHLSLNodeSymbol(uint32_t NameId, uint16_t FileSourceId, uint16_t SourceLineCount, uint32_t SourceLineStart, uint32_t SourceColumnStart, uint32_t SourceColumnEnd) @@ -208,18 +240,38 @@ struct DxcHLSLNodeSymbol { SourceColumnEndLo(uint16_t(SourceColumnEnd)), ColumnHiSourceLinePad((SourceColumnStart >> 16) | (SourceColumnEnd >> 16 << 6) | - (SourceLineStart << 12)) { + (SourceLineStart << 12)) {} + +public: + + DxcHLSLNodeSymbol() = default; + + [[nodiscard]] static DxcReflectionError + Initialize(DxcHLSLNodeSymbol &Symbol, uint32_t NameId, uint16_t FileSourceId, + uint16_t SourceLineCount, uint32_t SourceLineStart, + uint32_t SourceColumnStart, uint32_t SourceColumnEnd) { if (SourceColumnStart >= (1u << 22)) - throw std::invalid_argument("SourceColumnStart out of bounds"); + return DXC_REFLECT_ERR("SourceColumnStart out of bounds"); if (SourceColumnEnd >= (1u << 22)) - throw std::invalid_argument("SourceColumnEnd out of bounds"); + return DXC_REFLECT_ERR("SourceColumnEnd out of bounds"); if (SourceLineStart >= ((1u << 20) - 1)) - throw std::invalid_argument("SourceLineStart out of bounds"); + return DXC_REFLECT_ERR("SourceLineStart out of bounds"); + + Symbol = + DxcHLSLNodeSymbol(NameId, FileSourceId, SourceLineCount, + SourceLineStart, SourceColumnStart, SourceColumnEnd); + return DxcReflectionSuccess; } + + uint32_t GetNameId() const { return NameId; } + + uint16_t GetFileSourceId() const { return FileSourceId; } + uint16_t GetSourceLineCount() const { return SourceLineCount; } + uint32_t GetSourceLineStart() const { return uint32_t(ColumnHiSourceLinePad >> 12); } @@ -282,23 +334,36 @@ struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC without duplicating // - if HasConditionVar(): a variable in the condition // - NodeCount children (If: children ex. else body, For: init children) // - Rest of the body (If: else body, otherwise: normal body) -struct DxcHLSLStatement { +class DxcHLSLStatement { uint32_t NodeId; uint32_t NodeCount_HasConditionVar_HasElse; - DxcHLSLStatement() = default; - DxcHLSLStatement(uint32_t NodeId, uint32_t NodeCount, bool HasConditionVar, bool IfAndHasElse) : NodeId(NodeId), NodeCount_HasConditionVar_HasElse(NodeCount | (HasConditionVar ? (1u << 30) : 0) | - (IfAndHasElse ? (1u << 31) : 0)) { + (IfAndHasElse ? (1u << 31) : 0)) {} + +public: + + DxcHLSLStatement() = default; + + [[nodiscard]] static DxcReflectionError + Initialize(DxcHLSLStatement &Statement, uint32_t NodeId, uint32_t NodeCount, + bool HasConditionVar, bool IfAndHasElse) { + if (NodeCount >= (1u << 30)) - throw std::invalid_argument("NodeCount out of bounds"); + return DXC_REFLECT_ERR("NodeCount out of bounds"); + + Statement = + DxcHLSLStatement(NodeId, NodeCount, HasConditionVar, IfAndHasElse); + return DxcReflectionSuccess; } + uint32_t GetNodeId() const { return NodeId; } + // Node count represents one of two things: // - If: The amount of nodes in the 'if' part of the branch (to be able to // find the else part) @@ -319,24 +384,35 @@ struct DxcHLSLStatement { } }; -struct DxcHLSLFunction { +class DxcHLSLFunction { uint32_t NodeId; uint32_t NumParametersHasReturnAndDefinition; - DxcHLSLFunction() = default; - DxcHLSLFunction(uint32_t NodeId, uint32_t NumParameters, bool HasReturn, bool HasDefinition) : NodeId(NodeId), NumParametersHasReturnAndDefinition(NumParameters | (HasReturn ? (1u << 30) : 0) | - (HasDefinition ? (1u << 31) : 0)) { + (HasDefinition ? (1u << 31) : 0)) { } + +public: + + DxcHLSLFunction() = default; + + [[nodiscard]] static DxcReflectionError Initialize(DxcHLSLFunction &Function, uint32_t NodeId, + uint32_t NumParameters, bool HasReturn, + bool HasDefinition) { if (NumParameters >= (1u << 30)) - throw std::invalid_argument("NumParameters out of bounds"); + return DXC_REFLECT_ERR("NumParameters out of bounds"); + + Function = DxcHLSLFunction(NodeId, NumParameters, HasReturn, HasDefinition); + return DxcReflectionSuccess; } + uint32_t GetNodeId() const { return NodeId; } + uint32_t GetNumParameters() const { return NumParametersHasReturnAndDefinition << 2 >> 2; } @@ -356,9 +432,9 @@ struct DxcHLSLFunction { } }; -struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus - // the Name (and uID replaced with NodeID) and added - // arrayIndex and better packing +class DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus + // the Name (and uID replaced with NodeID) and added + // arrayIndex and better packing union { struct { @@ -383,30 +459,56 @@ struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus uint64_t ArrayIdBufferId; }; - DxcHLSLRegister() = default; DxcHLSLRegister(D3D_SHADER_INPUT_TYPE Type, uint32_t BindCount, uint32_t uFlags, D3D_RESOURCE_RETURN_TYPE ReturnType, D3D_SRV_DIMENSION Dimension, uint32_t NodeId, uint32_t ArrayId, uint32_t BufferId) : Type(Type), BindCount(BindCount), uFlags(uFlags), ReturnType(ReturnType), Dimension(Dimension), NodeId(NodeId), - ArrayId(ArrayId), BufferId(BufferId) { + ArrayId(ArrayId), BufferId(BufferId) {} + +public: + DxcHLSLRegister() = default; + + [[nodiscard]] static DxcReflectionError + Initialize(DxcHLSLRegister &Register, D3D_SHADER_INPUT_TYPE Type, + uint32_t BindCount, uint32_t uFlags, + D3D_RESOURCE_RETURN_TYPE ReturnType, D3D_SRV_DIMENSION Dimension, + uint32_t NodeId, uint32_t ArrayId, uint32_t BufferId) { if (Type < D3D_SIT_CBUFFER || Type > D3D_SIT_UAV_FEEDBACKTEXTURE) - throw std::invalid_argument("Invalid type"); + return DXC_REFLECT_ERR("Invalid type"); - if (ReturnType < 0 || - ReturnType > D3D_RETURN_TYPE_CONTINUED) - throw std::invalid_argument("Invalid return type"); + if (ReturnType < 0 || ReturnType > D3D_RETURN_TYPE_CONTINUED) + return DXC_REFLECT_ERR("Invalid return type"); if (Dimension < D3D_SRV_DIMENSION_UNKNOWN || Dimension > D3D_SRV_DIMENSION_BUFFEREX) - throw std::invalid_argument("Invalid srv dimension"); + return DXC_REFLECT_ERR("Invalid srv dimension"); if (uFlags >> 8) - throw std::invalid_argument("Invalid user flags"); + return DXC_REFLECT_ERR("Invalid user flags"); + + Register = DxcHLSLRegister(Type, BindCount, uFlags, ReturnType, Dimension, + NodeId, ArrayId, BufferId); + return DxcReflectionSuccess; } + D3D_RESOURCE_RETURN_TYPE GetReturnType() const { + return D3D_RESOURCE_RETURN_TYPE(ReturnType); + } + + D3D_SRV_DIMENSION GetDimension() const { + return D3D_SRV_DIMENSION(Dimension); + } + + uint32_t GetFlags() const { return uFlags; } + D3D_SHADER_INPUT_TYPE GetType() const { return D3D_SHADER_INPUT_TYPE(Type); } + uint32_t GetBindCount() const { return BindCount; } + uint32_t GetNodeId() const { return NodeId; } + uint32_t GetArrayId() const { return ArrayId; } + uint32_t GetBufferId() const { return BufferId; } + bool operator==(const DxcHLSLRegister &other) const { return TypeDimensionReturnTypeFlagsBindCount == other.TypeDimensionReturnTypeFlagsBindCount && @@ -414,19 +516,27 @@ struct DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus } }; -struct DxcHLSLArray { +class DxcHLSLArray { uint32_t ArrayElemStart; - DxcHLSLArray() = default; DxcHLSLArray(uint32_t ArrayElem, uint32_t ArrayStart) - : ArrayElemStart((ArrayElem << 26) | ArrayStart) { + : ArrayElemStart((ArrayElem << 26) | ArrayStart) {} + +public: + + DxcHLSLArray() = default; + + [[nodiscard]] static DxcReflectionError Initialize(DxcHLSLArray &Arr, uint32_t ArrayElem, uint32_t ArrayStart) { if (ArrayElem <= 1 || ArrayElem > 32) - throw std::invalid_argument("ArrayElem out of bounds"); + return DXC_REFLECT_ERR("ArrayElem out of bounds"); if (ArrayStart >= (1u << 26)) - throw std::invalid_argument("ArrayStart out of bounds"); + return DXC_REFLECT_ERR("ArrayStart out of bounds"); + + Arr = DxcHLSLArray(ArrayElem, ArrayStart); + return DxcReflectionSuccess; } bool operator==(const DxcHLSLArray &Other) const { @@ -465,7 +575,7 @@ struct DxcHLSLArrayOrElements { } }; -struct DxcHLSLType { // Almost maps to CShaderReflectionType and +class DxcHLSLType { // Almost maps to CShaderReflectionType and // D3D12_SHADER_TYPE_DESC, but tightly packed and // easily serializable @@ -486,6 +596,19 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and DxcHLSLArrayOrElements UnderlyingArray; //No sugar (e.g. F32x4a4 in using F32x4a4 = F32x4[4] becomes float4[4]) + DxcHLSLType(uint32_t BaseClass, + DxcHLSLArrayOrElements ElementsOrArrayIdUnderlying, + D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE Type, + uint8_t Rows, uint8_t Columns, uint32_t MembersCount, + uint32_t MembersStart, uint32_t InterfaceOffset, + uint32_t InterfaceCount) + : MemberData(MembersStart | (MembersCount << 24)), Class(Class), + Type(Type), Rows(Rows), Columns(Columns), + UnderlyingArray(ElementsOrArrayIdUnderlying), BaseClass(BaseClass), + InterfaceOffsetAndCount(InterfaceOffset | (InterfaceCount << 24)) {} + +public: + bool operator==(const DxcHLSLType &Other) const { return Other.MemberData == MemberData && Other.UnderlyingArray == UnderlyingArray && @@ -494,8 +617,23 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and InterfaceOffsetAndCount == Other.InterfaceOffsetAndCount; } + D3D_SHADER_VARIABLE_CLASS GetClass() const { + return D3D_SHADER_VARIABLE_CLASS(Class); + } + + D3D_SHADER_VARIABLE_TYPE GetType() const { + return D3D_SHADER_VARIABLE_TYPE(Type); + } + + uint8_t GetRows() const { return Rows; } + uint8_t GetColumns() const { return Columns; } + + uint32_t GetBaseClass() const { return BaseClass; } + uint32_t GetMemberCount() const { return MemberData >> 24; } uint32_t GetMemberStart() const { return MemberData << 8 >> 8; } + + DxcHLSLArrayOrElements GetUnderlyingArray() const { return UnderlyingArray; } uint32_t GetInterfaceCount() const { return InterfaceOffsetAndCount >> 24; } uint32_t GetInterfaceStart() const { @@ -503,34 +641,37 @@ struct DxcHLSLType { // Almost maps to CShaderReflectionType and } DxcHLSLType() = default; - DxcHLSLType(uint32_t BaseClass, - DxcHLSLArrayOrElements ElementsOrArrayIdUnderlying, - D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE Type, - uint8_t Rows, uint8_t Columns, uint32_t MembersCount, - uint32_t MembersStart, uint32_t InterfaceOffset, - uint32_t InterfaceCount) - : MemberData(MembersStart | (MembersCount << 24)), Class(Class), - Type(Type), Rows(Rows), Columns(Columns), - UnderlyingArray(ElementsOrArrayIdUnderlying), BaseClass(BaseClass), - InterfaceOffsetAndCount(InterfaceOffset | (InterfaceCount << 24)) { + + [[nodiscard]] static DxcReflectionError + Initialize(DxcHLSLType &Type, uint32_t BaseClass, + DxcHLSLArrayOrElements ElementsOrArrayIdUnderlying, + D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE VariableType, + uint8_t Rows, uint8_t Columns, uint32_t MembersCount, + uint32_t MembersStart, uint32_t InterfaceOffset, + uint32_t InterfaceCount) { if (Class < D3D_SVC_SCALAR || Class > D3D_SVC_INTERFACE_POINTER) - throw std::invalid_argument("Invalid class"); + return DXC_REFLECT_ERR("Invalid class"); - if (Type < D3D_SVT_VOID || Type > D3D_SVT_UINT64) - throw std::invalid_argument("Invalid type"); + if (VariableType < D3D_SVT_VOID || VariableType > D3D_SVT_UINT64) + return DXC_REFLECT_ERR("Invalid type"); if (MembersStart >= (1u << 24)) - throw std::invalid_argument("Member start out of bounds"); + return DXC_REFLECT_ERR("Member start out of bounds"); if (InterfaceOffset >= (1u << 24)) - throw std::invalid_argument("Interface start out of bounds"); + return DXC_REFLECT_ERR("Interface start out of bounds"); if (MembersCount >= (1u << 8)) - throw std::invalid_argument("Member count out of bounds"); + return DXC_REFLECT_ERR("Member count out of bounds"); if (InterfaceCount >= (1u << 8)) - throw std::invalid_argument("Interface count out of bounds"); + return DXC_REFLECT_ERR("Interface count out of bounds"); + + Type = DxcHLSLType(BaseClass, ElementsOrArrayIdUnderlying, Class, + VariableType, Rows, Columns, MembersCount, MembersStart, + InterfaceOffset, InterfaceCount); + return DxcReflectionSuccess; } }; @@ -570,18 +711,25 @@ struct DxcHLSLBuffer { // Almost maps to CShaderReflectionConstantBuffer and } }; -struct DxcHLSLAnnotation { +class DxcHLSLAnnotation { uint32_t StringNonDebugAndIsBuiltin; - DxcHLSLAnnotation() = default; - DxcHLSLAnnotation(uint32_t StringNonDebug, bool IsBuiltin) : StringNonDebugAndIsBuiltin(StringNonDebug | - (IsBuiltin ? (1u << 31) : 0)) { + (IsBuiltin ? (1u << 31) : 0)) {} +public: + + DxcHLSLAnnotation() = default; + + [[nodiscard]] static DxcReflectionError + Initialize(DxcHLSLAnnotation &Annotation, uint32_t StringNonDebug, bool IsBuiltin) { if (StringNonDebug >= (1u << 31)) - throw std::invalid_argument("String non debug out of bounds"); + return DXC_REFLECT_ERR("String non debug out of bounds"); + + Annotation = DxcHLSLAnnotation(StringNonDebug, IsBuiltin); + return DxcReflectionSuccess; } bool operator==(const DxcHLSLAnnotation &other) const { @@ -647,7 +795,7 @@ struct DxcHLSLReflectionData { std::unordered_map FullyResolvedToMemberId; uint32_t RegisterString(const std::string &Name, bool IsNonDebug); - uint32_t PushArray(uint32_t ArraySizeFlat, + [[nodiscard]] DxcReflectionError PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, const std::vector &ArraySize); void RegisterTypeList(const std::vector &TypeIds, uint32_t &Offset, diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 75d2288eec..d796b67978 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -54,15 +54,17 @@ uint32_t DxcHLSLReflectionData::RegisterString(const std::string &Name, return stringId; } -uint32_t -DxcHLSLReflectionData::PushArray(uint32_t ArraySizeFlat, +[[nodiscard]] DxcReflectionError +DxcHLSLReflectionData::PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, const std::vector &ArraySize) { - if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) - return uint32_t(-1); + if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) { + ArrayId = uint32_t(-1); + return DxcReflectionSuccess; + } if (Arrays.size() >= uint32_t((1u << 31) - 1)) - throw std::invalid_argument("Arrays would overflow"); + return DXC_REFLECT_ERR("Arrays would overflow"); uint32_t arrayId = uint32_t(Arrays.size()); @@ -70,7 +72,7 @@ DxcHLSLReflectionData::PushArray(uint32_t ArraySizeFlat, uint32_t numArrayElements = std::min(size_t(32), ArraySize.size()); if (ArraySizes.size() + numArrayElements >= ((1u << 26) - 1)) - throw std::invalid_argument("Array elements would overflow"); + return DXC_REFLECT_ERR("Array elements would overflow"); for (uint32_t i = 0; i < ArraySize.size() && i < 8; ++i) { @@ -84,14 +86,21 @@ DxcHLSLReflectionData::PushArray(uint32_t ArraySizeFlat, ArraySizes.push_back(arraySize); } - DxcHLSLArray arr = {numArrayElements, arrayCountStart}; + DxcHLSLArray arr; + + if (DxcReflectionError err = + DxcHLSLArray::Initialize(arr, numArrayElements, arrayCountStart)) + return err; for (uint32_t i = 0; i < Arrays.size(); ++i) - if (Arrays[i] == arr) - return i; + if (Arrays[i] == arr) { + ArrayId = i; + return DxcReflectionSuccess; + } Arrays.push_back(arr); - return arrayId; + ArrayId = arrayId; + return DxcReflectionSuccess; } void DxcHLSLReflectionData::RegisterTypeList( @@ -151,9 +160,9 @@ void DxcHLSLReflectionData::RegisterTypeList( static std::string RegisterGetArraySize(const DxcHLSLReflectionData &Refl, const DxcHLSLRegister ®) { - if (reg.ArrayId != (uint32_t)-1) { + if (reg.GetArrayId() != (uint32_t)-1) { - DxcHLSLArray arr = Refl.Arrays[reg.ArrayId]; + DxcHLSLArray arr = Refl.Arrays[reg.GetArrayId()]; std::string str; for (uint32_t i = 0; i < arr.ArrayElem(); ++i) @@ -162,7 +171,8 @@ static std::string RegisterGetArraySize(const DxcHLSLReflectionData &Refl, const return str; } - return reg.BindCount > 1 ? "[" + std::to_string(reg.BindCount) + "]" : ""; + return reg.GetBindCount() > 1 ? "[" + std::to_string(reg.GetBindCount()) + "]" + : ""; } static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { @@ -225,7 +235,7 @@ static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, std::string type; - if (Type.Class != D3D_SVC_STRUCT && Type.Class != D3D_SVC_INTERFACE_CLASS) { + if (Type.GetClass() != D3D_SVC_STRUCT && Type.GetClass() != D3D_SVC_INTERFACE_CLASS) { static const char *arr[] = {"void", "bool", @@ -291,26 +301,27 @@ static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, "int64_t", "uint64_t"}; - const char *ptr = arr[Type.Type]; + const char *ptr = arr[Type.GetType()]; if (ptr) type = ptr; } - switch (Type.Class) { + switch (Type.GetClass()) { case D3D_SVC_MATRIX_ROWS: case D3D_SVC_VECTOR: - type += std::to_string(Type.Columns); + type += std::to_string(Type.GetColumns()); - if (Type.Class == D3D_SVC_MATRIX_ROWS) - type += "x" + std::to_string(Type.Rows); + if (Type.GetClass() == D3D_SVC_MATRIX_ROWS) + type += "x" + std::to_string(Type.GetRows()); break; case D3D_SVC_MATRIX_COLUMNS: - type += std::to_string(Type.Rows) + "x" + std::to_string(Type.Columns); + type += std::to_string(Type.GetRows()) + "x" + + std::to_string(Type.GetColumns()); break; } @@ -322,7 +333,7 @@ static std::string PrintTypeInfo(const DxcHLSLReflectionData &Refl, const DxcHLSLTypeSymbol &Symbol, const std::string &PreviousTypeName) { - std::string result = PrintArray(Refl, Type.UnderlyingArray); + std::string result = PrintArray(Refl, Type.GetUnderlyingArray()); // Obtain type name (returns empty if it's not a builtin type) @@ -353,8 +364,8 @@ static void RecursePrintType(const DxcHLSLReflectionData &Refl, uint32_t TypeId, printf("%s%s%s%s\n", std::string(Depth, '\t').c_str(), Prefix, name.c_str(), PrintTypeInfo(Refl, type, symbol, name).c_str()); - if (type.BaseClass != uint32_t(-1)) - RecursePrintType(Refl, type.BaseClass, Depth + 1, + if (type.GetBaseClass() != uint32_t(-1)) + RecursePrintType(Refl, type.GetBaseClass(), Depth + 1, (std::string("BaseClass ") + Prefix).c_str()); for (uint32_t i = 0; i < type.GetInterfaceCount(); ++i) { @@ -388,7 +399,8 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, if (!isThroughFwdDecl) printf("%s%s %s%s\n", std::string(Depth - 1, '\t').c_str(), NodeTypeToString(node.GetNodeType()).c_str(), - hasSymbols ? Refl.Strings[Refl.NodeSymbols[NodeId].NameId].c_str() + hasSymbols + ? Refl.Strings[Refl.NodeSymbols[NodeId].GetNameId()].c_str() : "(unknown)", node.IsFwdDeclare() ? " (declaration)" : (!isThroughFwdDecl && node.IsFwdBckDefined() @@ -421,7 +433,7 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, const DxcHLSLRegister ® = Refl.Registers[localId]; - if (reg.ArrayId == (uint32_t)-1 && reg.BindCount == 1) + if (reg.GetArrayId() == (uint32_t)-1 && reg.GetBindCount() == 1) break; printf("%s%s\n", std::string(Depth, '\t').c_str(), @@ -434,8 +446,8 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, const DxcHLSLType &type = Refl.Types[localId]; - if (type.BaseClass != uint32_t(-1)) - RecursePrintType(Refl, type.BaseClass, Depth, "BaseClass "); + if (type.GetBaseClass() != uint32_t(-1)) + RecursePrintType(Refl, type.GetBaseClass(), Depth, "BaseClass "); for (uint32_t i = 0; i < type.GetInterfaceCount(); ++i) { @@ -489,7 +501,7 @@ uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, case D3D12_HLSL_NODE_TYPE_IF: { const DxcHLSLStatement &Stmt = Refl.Statements[localId]; - const DxcHLSLNode &Node = Refl.Nodes[Stmt.NodeId]; + const DxcHLSLNode &Node = Refl.Nodes[Stmt.GetNodeId()]; uint32_t bodyNodes = Node.GetChildCount() - Stmt.GetNodeCount() - Stmt.HasConditionVar(); @@ -773,7 +785,7 @@ void RecurseNameGenerationType(DxcHLSLReflectionData &Refl, uint32_t TypeId, const DxcHLSLType &type = Refl.Types[TypeId]; - if (type.Class == D3D_SVC_STRUCT) + if (type.GetClass() == D3D_SVC_STRUCT) for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { uint32_t memberId = i + type.GetMemberStart(); @@ -798,7 +810,7 @@ uint32_t RecurseNameGeneration(DxcHLSLReflectionData &Refl, uint32_t NodeId, node = Refl.Nodes[NodeId]; } - std::string self = Refl.Strings[Refl.NodeSymbols[NodeId].NameId]; + std::string self = Refl.Strings[Refl.NodeSymbols[NodeId].GetNameId()]; if (self.empty() && NodeId) self = std::to_string(LocalId); @@ -821,7 +833,7 @@ uint32_t RecurseNameGeneration(DxcHLSLReflectionData &Refl, uint32_t NodeId, uint32_t typeId = node.GetLocalId(); const DxcHLSLType &type = Refl.Types[typeId]; - if (type.Class == D3D_SVC_STRUCT) + if (type.GetClass() == D3D_SVC_STRUCT) for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { uint32_t memberId = i + type.GetMemberStart(); @@ -952,9 +964,9 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLNode &node = Nodes[i]; - if (hasSymbolInfo && (NodeSymbols[i].NameId >= header.Strings || - (NodeSymbols[i].FileSourceId != uint16_t(-1) && - NodeSymbols[i].FileSourceId >= header.Sources))) + if (hasSymbolInfo && (NodeSymbols[i].GetNameId() >= header.Strings || + (NodeSymbols[i].GetFileSourceId() != uint16_t(-1) && + NodeSymbols[i].GetFileSourceId() >= header.Sources))) throw std::invalid_argument("Node " + std::to_string(i) + " points to invalid name or file name"); @@ -1092,29 +1104,28 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLRegister ® = Registers[i]; - if( - reg.NodeId >= header.Nodes || - Nodes[reg.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER || - Nodes[reg.NodeId].GetLocalId() != i + if(reg.GetNodeId() >= header.Nodes || + Nodes[reg.GetNodeId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER || + Nodes[reg.GetNodeId()].GetLocalId() != i ) throw std::invalid_argument("Register " + std::to_string(i) + " points to an invalid nodeId"); - if (reg.Type > D3D_SIT_UAV_FEEDBACKTEXTURE || - reg.ReturnType > D3D_RETURN_TYPE_CONTINUED || - reg.Dimension > D3D_SRV_DIMENSION_BUFFEREX || !reg.BindCount || - (reg.ArrayId != uint32_t(-1) && reg.ArrayId >= header.Arrays) || - (reg.ArrayId != uint32_t(-1) && reg.BindCount <= 1)) + if (reg.GetType() > D3D_SIT_UAV_FEEDBACKTEXTURE || + reg.GetReturnType() > D3D_RETURN_TYPE_CONTINUED || + reg.GetDimension() > D3D_SRV_DIMENSION_BUFFEREX || !reg.GetBindCount() || + (reg.GetArrayId() != uint32_t(-1) && reg.GetArrayId() >= header.Arrays) || + (reg.GetArrayId() != uint32_t(-1) && reg.GetBindCount() <= 1)) throw std::invalid_argument( "Register " + std::to_string(i) + " invalid type, returnType, bindCount, array or dimension"); - D3D_CBUFFER_TYPE bufferType = GetBufferType(reg.Type); + D3D_CBUFFER_TYPE bufferType = GetBufferType(reg.GetType()); if(bufferType != D3D_CT_INTERFACE_POINTERS) { - if (reg.BufferId >= header.Buffers || - Buffers[reg.BufferId].NodeId != reg.NodeId || - Buffers[reg.BufferId].Type != bufferType) + if (reg.GetBufferId() >= header.Buffers || + Buffers[reg.GetBufferId()].NodeId != reg.GetNodeId() || + Buffers[reg.GetBufferId()].Type != bufferType) throw std::invalid_argument("Register " + std::to_string(i) + " invalid buffer referenced by register"); } @@ -1124,21 +1135,22 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLFunction &func = Functions[i]; - if (func.NodeId >= header.Nodes || - Nodes[func.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION || - Nodes[func.NodeId].GetLocalId() != i) + if (func.GetNodeId() >= header.Nodes || + Nodes[func.GetNodeId()].GetNodeType() != + D3D12_HLSL_NODE_TYPE_FUNCTION || + Nodes[func.GetNodeId()].GetLocalId() != i) throw std::invalid_argument("Function " + std::to_string(i) + " points to an invalid nodeId"); uint32_t paramCount = func.GetNumParameters() + func.HasReturn(); - if (Nodes[func.NodeId].GetChildCount() < paramCount) + if (Nodes[func.GetNodeId()].GetChildCount() < paramCount) throw std::invalid_argument("Function " + std::to_string(i) + " is missing parameters and/or return"); for (uint32_t j = 0; j < paramCount; ++j) - if (Nodes[func.NodeId + 1 + j].GetParentId() != func.NodeId || - Nodes[func.NodeId + 1 + j].GetNodeType() != + if (Nodes[func.GetNodeId() + 1 + j].GetParentId() != func.GetNodeId() || + Nodes[func.GetNodeId() + 1 + j].GetNodeType() != D3D12_HLSL_NODE_TYPE_PARAMETER) throw std::invalid_argument( "Function " + std::to_string(i) + @@ -1212,7 +1224,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (buf.NodeId >= header.Nodes || Nodes[buf.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER || Nodes[buf.NodeId].GetLocalId() >= header.Registers || - Registers[Nodes[buf.NodeId].GetLocalId()].BufferId != i) + Registers[Nodes[buf.NodeId].GetLocalId()].GetBufferId() != i) throw std::invalid_argument("Buffer " + std::to_string(i) + " points to an invalid nodeId"); @@ -1304,25 +1316,26 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLStatement &Stmt = Statements[i]; - if (Stmt.NodeId >= header.Nodes || Nodes[Stmt.NodeId].GetLocalId() != i) + if (Stmt.GetNodeId() >= header.Nodes || + Nodes[Stmt.GetNodeId()].GetLocalId() != i) throw std::invalid_argument("Statement " + std::to_string(i) + " points to an invalid nodeId"); bool condVar = Stmt.HasConditionVar(); uint32_t minParamCount = Stmt.GetNodeCount() + condVar; - const DxcHLSLNode &node = Nodes[Stmt.NodeId]; + const DxcHLSLNode &node = Nodes[Stmt.GetNodeId()]; if (node.GetChildCount() < minParamCount) throw std::invalid_argument("Statement " + std::to_string(i) + " didn't have required child nodes"); - if (condVar && - Nodes[Stmt.NodeId + 1].GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) + if (condVar && Nodes[Stmt.GetNodeId() + 1].GetNodeType() != + D3D12_HLSL_NODE_TYPE_VARIABLE) throw std::invalid_argument( "Statement " + std::to_string(i) + " has condition variable but first child is not a variable"); - switch (Nodes[Stmt.NodeId].GetNodeType()) { + switch (Nodes[Stmt.GetNodeId()].GetNodeType()) { case D3D12_HLSL_NODE_TYPE_IF: case D3D12_HLSL_NODE_TYPE_WHILE: case D3D12_HLSL_NODE_TYPE_FOR: @@ -1349,21 +1362,23 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes throw std::invalid_argument("Type " + std::to_string(i) + " points to an invalid string"); - if ((type.BaseClass != uint32_t(-1) && type.BaseClass >= header.Types) || + if ((type.GetBaseClass() != uint32_t(-1) && + type.GetBaseClass() >= header.Types) || type.GetMemberStart() + type.GetMemberCount() > header.Members || type.GetInterfaceStart() + type.GetInterfaceCount() > header.TypeListCount || - (type.UnderlyingArray.ElementsOrArrayId >> 31 && - (type.UnderlyingArray.ElementsOrArrayId << 1 >> 1) >= header.Arrays)) + (type.GetUnderlyingArray().ElementsOrArrayId >> 31 && + (type.GetUnderlyingArray().ElementsOrArrayId << 1 >> 1) >= + header.Arrays)) throw std::invalid_argument( "Type " + std::to_string(i) + " points to an invalid string, array, base class or member"); - switch (type.Class) { + switch (type.GetClass()) { case D3D_SVC_SCALAR: - if (type.Columns != 1) + if (type.GetColumns() != 1) throw std::invalid_argument("Type (scalar) " + std::to_string(i) + " should have columns == 1"); @@ -1371,7 +1386,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D_SVC_VECTOR: - if (type.Rows != 1) + if (type.GetRows() != 1) throw std::invalid_argument("Type (scalar/vector) " + std::to_string(i) + " should have rows == 1"); @@ -1381,12 +1396,13 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D_SVC_MATRIX_ROWS: case D3D_SVC_MATRIX_COLUMNS: - if (!type.Rows || !type.Columns || type.Rows > 128 || type.Columns > 128) + if (!type.GetRows() || !type.GetColumns() || type.GetRows() > 128 || + type.GetColumns() > 128) throw std::invalid_argument("Type (scalar/vector/matrix) " + std::to_string(i) + " has invalid rows or columns"); - switch (type.Type) { + switch (type.GetType()) { case D3D_SVT_BOOL: case D3D_SVT_INT: case D3D_SVT_FLOAT: @@ -1423,12 +1439,12 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D_SVC_INTERFACE_CLASS: - if (type.Type) + if (type.GetType()) throw std::invalid_argument("Type (struct) " + std::to_string(i) + " shouldn't have rows or columns"); - if (type.Rows || type.Columns) + if (type.GetRows() || type.GetColumns()) throw std::invalid_argument("Type (struct) " + std::to_string(i) + " shouldn't have rows or columns"); @@ -1437,7 +1453,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D_SVC_OBJECT: - switch (type.Type) { + switch (type.GetType()) { case D3D_SVT_STRING: case D3D_SVT_TEXTURE1D: @@ -1472,7 +1488,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes " is of invalid type"); } - if (type.Rows || type.Columns) + if (type.GetRows() || type.GetColumns()) throw std::invalid_argument("Type (object) " + std::to_string(i) + " shouldn't have rows or columns"); @@ -1500,7 +1516,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes "Node " + std::to_string(i) + " (fwd/bck declare) points to element that of incompatible type"); - if (hasSymbolInfo && NodeSymbols[fwdBack].NameId != NodeSymbols[i].NameId) + if (hasSymbolInfo && NodeSymbols[fwdBack].GetNameId() != NodeSymbols[i].GetNameId()) throw std::invalid_argument( "Node " + std::to_string(i) + " (fwd/bck declare) have mismatching name"); diff --git a/tools/clang/tools/libclang/dxcreflection_from_ast.cpp b/tools/clang/tools/libclang/dxcreflection_from_ast.cpp index ee0ae688fd..1f5d18ff3d 100644 --- a/tools/clang/tools/libclang/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/libclang/dxcreflection_from_ast.cpp @@ -24,8 +24,8 @@ using namespace clang; namespace hlsl { -static uint32_t -PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, +static [[nodiscard]] DxcReflectionError +PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManager &SM, const LangOptions &LangOpts, const std::string &UnqualifiedName, const Decl *DeclSelf, D3D12_HLSL_NODE_TYPE Type, uint32_t ParentNodeId, uint32_t LocalId, @@ -34,10 +34,10 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, { if (Refl.Nodes.size() >= (1u << 24)) - throw std::invalid_argument("Nodes overflow"); + return DXC_REFLECT_ERR("Nodes overflow"); if (LocalId >= (1u << 24)) - throw std::invalid_argument("LocalId overflow"); + return DXC_REFLECT_ERR("LocalId overflow"); uint32_t nodeId = Refl.Nodes.size(); @@ -51,13 +51,18 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, if (const AnnotateAttr *annotate = dyn_cast(attr)) { if (Refl.Annotations.size() >= (1u << 16)) - throw std::invalid_argument("Out of annotations"); + return DXC_REFLECT_ERR("Out of annotations"); - Refl.Annotations.push_back(DxcHLSLAnnotation( - Refl.RegisterString(annotate->getAnnotation().str(), true), false)); + Refl.Annotations.push_back({}); + + if (DxcReflectionError err = DxcHLSLAnnotation::Initialize( + Refl.Annotations.back(), + Refl.RegisterString(annotate->getAnnotation().str(), true), + false)) + return err; if (annotationCount >= uint8_t(-1)) - throw std::invalid_argument("Annotation count out of bounds"); + return DXC_REFLECT_ERR("Annotation count out of bounds"); ++annotationCount; @@ -65,18 +70,21 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, dyn_cast(attr)) { if (Refl.Annotations.size() >= (1u << 16)) - throw std::invalid_argument("Out of annotations"); + return DXC_REFLECT_ERR("Out of annotations"); + + Refl.Annotations.push_back({}); - Refl.Annotations.push_back(DxcHLSLAnnotation( - Refl.RegisterString( - "shader(\"" + shaderAttr->getStage().str() + "\")", true), - true)); + if (DxcReflectionError err = DxcHLSLAnnotation::Initialize( + Refl.Annotations.back(), + Refl.RegisterString( + "shader(\"" + shaderAttr->getStage().str() + "\")", true), + true)) + return err; if (annotationCount >= uint8_t(-1)) - throw std::invalid_argument("Annotation count out of bounds"); + return DXC_REFLECT_ERR("Annotation count out of bounds"); ++annotationCount; - } } @@ -117,8 +125,10 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, fwdDeclare = rec->getCanonicalDecl(); canHaveFwdDeclare = true; - if (isFwdDeclare && rec->isImplicit()) //Inner ghost node - return uint32_t(-1); + if (isFwdDeclare && rec->isImplicit()) { // Inner ghost node + NodeId = uint32_t(-1); + return DxcReflectionSuccess; + } } } @@ -129,16 +139,20 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, assert(FwdDecls && "Fwd decl requires FwdDecls map to be present"); // Multiple fwd declare, ignore - if (isFwdDeclare && FwdDecls->find(fwdDeclare) != FwdDecls->end()) - return uint32_t(-1); + if (isFwdDeclare && FwdDecls->find(fwdDeclare) != FwdDecls->end()) { + NodeId = uint32_t(-1); + return DxcReflectionSuccess; + } if (isFwdDeclare) (*FwdDecls)[fwdDeclare] = currId; } - Refl.Nodes.push_back(DxcHLSLNode{Type, isFwdDeclare, LocalId, annotationStart, - 0, ParentNodeId, annotationCount, - semanticId}); + Refl.Nodes.push_back({}); + if (DxcReflectionError err = DxcHLSLNode::Initialize( + Refl.Nodes.back(), Type, isFwdDeclare, LocalId, annotationStart, 0, + ParentNodeId, annotationCount, semanticId)) + return err; if (Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { @@ -174,7 +188,7 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, std::string fileName = presumed.getFilename(); if (fileName != presumedEnd.getFilename()) - throw std::invalid_argument("End and start are not in the same file"); + return DXC_REFLECT_ERR("End and start are not in the same file"); auto it = Refl.StringToSourceId.find(fileName); uint32_t i; @@ -190,19 +204,19 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, } if (i >= 65535) - throw std::invalid_argument("Source file count is limited to 16-bit"); + return DXC_REFLECT_ERR("Source file count is limited to 16-bit"); if ((endLine - startLine) >= 65535) - throw std::invalid_argument("Source line count is limited to 16-bit"); + return DXC_REFLECT_ERR("Source line count is limited to 16-bit"); if (startLine >= 1048576) - throw std::invalid_argument("Source line start is limited to 20-bit"); + return DXC_REFLECT_ERR("Source line start is limited to 20-bit"); if (startCol >= (1u << 22)) - throw std::invalid_argument("Column start is limited to 22-bit"); + return DXC_REFLECT_ERR("Column start is limited to 22-bit"); if (endCol >= (1u << 22)) - throw std::invalid_argument("Column end is limited to 22-bit"); + return DXC_REFLECT_ERR("Column end is limited to 22-bit"); sourceLineCount = uint16_t(endLine - startLine + 1); sourceLineStart = startLine; @@ -214,9 +228,11 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, uint32_t nameId = Refl.RegisterString(UnqualifiedName, false); - Refl.NodeSymbols.push_back( - DxcHLSLNodeSymbol(nameId, sourceId, sourceLineCount, sourceLineStart, - sourceColumnStart, sourceColumnEnd)); + Refl.NodeSymbols.push_back({}); + + if(DxcReflectionError err = DxcHLSLNodeSymbol::Initialize(Refl.NodeSymbols.back(), nameId, sourceId, sourceLineCount, sourceLineStart, + sourceColumnStart, sourceColumnEnd)) + return err; } // Link @@ -224,20 +240,29 @@ PushNextNodeId(DxcHLSLReflectionData &Refl, const SourceManager &SM, if (DeclSelf && fwdDeclare != DeclSelf && fwdDeclare && !isFwdDeclare) { assert(FwdDecls && "Referencing fwd decl requires FwdDecls map to be present"); uint32_t fwd = (*FwdDecls)[fwdDeclare]; - Refl.Nodes[fwd].ResolveFwdDeclare(fwd, Refl.Nodes[currId], currId); + + if (DxcReflectionError err = + Refl.Nodes[fwd].ResolveFwdDeclare(fwd, Refl.Nodes[currId], currId)) + return err; } uint32_t parentParent = ParentNodeId; while (parentParent != 0) { + DxcHLSLNode &parent = Refl.Nodes[parentParent]; - parent.IncreaseChildCount(); + + if (DxcReflectionError err = parent.IncreaseChildCount()) + return err; + parentParent = parent.GetParentId(); } - Refl.Nodes[0].IncreaseChildCount(); + if (DxcReflectionError err = Refl.Nodes[0].IncreaseChildCount()) + return err; - return nodeId; + NodeId = nodeId; + return DxcReflectionSuccess; } struct DxcRegisterTypeInfo { @@ -459,7 +484,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); } -uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, +[[nodiscard]] DxcReflectionError GenerateTypeInfo(uint32_t &TypeId, ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, QualType Original, bool DefaultRowMaj) { // Unwrap array @@ -559,10 +584,19 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, //Two arrays; for display and for underlying - uint32_t arrayIdUnderlying = Refl.PushArray(arraySizeUnderlying, arrayElemUnderlying); + uint32_t arrayIdUnderlying; + + if (DxcReflectionError err = Refl.PushArray( + arrayIdUnderlying, arraySizeUnderlying, arrayElemUnderlying)) + return err; + DxcHLSLArrayOrElements elementsOrArrayIdUnderlying(arrayIdUnderlying, arraySizeUnderlying); - uint32_t arrayIdDisplay = Refl.PushArray(arraySizeDisplay, arrayElemDisplay); + uint32_t arrayIdDisplay; + if (DxcReflectionError err = + Refl.PushArray(arrayIdDisplay, arraySizeDisplay, arrayElemDisplay)) + return err; + DxcHLSLArrayOrElements elementsOrArrayIdDisplay(arrayIdDisplay, arraySizeDisplay); //Unwrap vector and matrix @@ -687,8 +721,11 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, uint32_t nameId = hasSymbols ? Refl.RegisterString(innerTypeName, false) : uint32_t(-1); - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, innerType, DefaultRowMaj); + uint32_t typeId; + + if (DxcReflectionError err = + GenerateTypeInfo(typeId, ASTCtx, Refl, innerType, DefaultRowMaj)) + return err; membersOffset = uint32_t(Refl.MemberTypeIds.size()); membersCount = 1; @@ -714,15 +751,23 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, cast(qualType->castAs()->getDecl()); if (BaseDecl->isInterface()) { - interfaces.push_back( - GenerateTypeInfo(ASTCtx, Refl, qualType, DefaultRowMaj)); + + uint32_t interfaceId; + + if (DxcReflectionError err = GenerateTypeInfo( + interfaceId, ASTCtx, Refl, qualType, DefaultRowMaj)) + return err; + + interfaces.push_back(interfaceId); continue; } assert(baseType == uint32_t(-1) && "Multiple base types isn't supported in HLSL"); - baseType = GenerateTypeInfo(ASTCtx, Refl, qualType, DefaultRowMaj); + if (DxcReflectionError err = GenerateTypeInfo( + baseType, ASTCtx, Refl, qualType, DefaultRowMaj)) + return err; } } @@ -756,7 +801,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, Refl.MemberTypeIds.resize(Refl.MemberTypeIds.size() + membersCount); if (Refl.MemberTypeIds.size() >= uint32_t(1u << 24)) - throw std::invalid_argument("Members out of bounds"); + return DXC_REFLECT_ERR("Members out of bounds"); } // Initialize member types (because it causes recursion) @@ -770,8 +815,13 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, if (!fieldDecl) continue; - Refl.MemberTypeIds[membersOffset + membersCount] = - GenerateTypeInfo(ASTCtx, Refl, fieldDecl->getType(), DefaultRowMaj); + uint32_t memberTypeId; + if (DxcReflectionError err = + GenerateTypeInfo(memberTypeId, ASTCtx, Refl, + fieldDecl->getType(), DefaultRowMaj)) + return err; + + Refl.MemberTypeIds[membersOffset + membersCount] = memberTypeId; ++membersCount; } @@ -871,7 +921,7 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, break; default: - throw std::invalid_argument("Invalid builtin type"); + return DXC_REFLECT_ERR("Invalid builtin type"); } } @@ -897,18 +947,21 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, //Insert if (Refl.Types.size() >= uint32_t(-1)) - throw std::invalid_argument("Type id out of bounds"); + return DXC_REFLECT_ERR("Type id out of bounds"); if (interfaces.size() >= uint8_t(-1)) - throw std::invalid_argument("Only allowing 256 interfaces"); + return DXC_REFLECT_ERR("Only allowing 256 interfaces"); uint32_t interfaceOffset = 0; uint8_t interfaceCount = 0; Refl.RegisterTypeList(interfaces, interfaceOffset, interfaceCount); - DxcHLSLType hlslType(baseType, elementsOrArrayIdUnderlying, cls, type, rows, columns, - membersCount, membersOffset, interfaceOffset, - interfaceCount); + DxcHLSLType hlslType; + if (DxcReflectionError err = DxcHLSLType::Initialize( + hlslType, baseType, elementsOrArrayIdUnderlying, cls, type, rows, + columns, membersCount, membersOffset, interfaceOffset, + interfaceCount)) + return err; uint32_t displayNameId = hasSymbols ? Refl.RegisterString(displayName, false) : uint32_t(-1); @@ -935,46 +988,50 @@ uint32_t GenerateTypeInfo(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, Refl.Types.push_back(hlslType); } - return i; + TypeId = i; + return DxcReflectionSuccess; } -static void FillReflectionRegisterAt( +[[nodiscard]] static DxcReflectionError FillReflectionRegisterAt( const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, ValueDecl *ValDesc, const std::vector &ArraySize, - DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId, - bool DefaultRowMaj) { + DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, + uint32_t ParentNodeId, bool DefaultRowMaj) { ArrayRef UA = ValDesc->getUnusualAnnotations(); DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); - uint32_t nodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), - ValDesc, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, - uint32_t(Refl.Registers.size())); + uint32_t nodeId; + if (DxcReflectionError err = PushNextNodeId( + nodeId, Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, + D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, + uint32_t(Refl.Registers.size()))) + return err; - uint32_t arrayId = Refl.PushArray(ArraySizeFlat, ArraySize); + uint32_t arrayId; + + if (DxcReflectionError err = + Refl.PushArray(arrayId, ArraySizeFlat, ArraySize)) + return err; uint32_t bufferId = 0; D3D_CBUFFER_TYPE bufferType = DxcHLSLReflectionData::GetBufferType(inputType.RegisterType); - - if(bufferType != D3D_CT_INTERFACE_POINTERS) { + + if (bufferType != D3D_CT_INTERFACE_POINTERS) { bufferId = uint32_t(Refl.Buffers.size()); Refl.Buffers.push_back({bufferType, nodeId}); } - DxcHLSLRegister regD3D12 = { - inputType.RegisterType, - ArraySizeFlat, - uint32_t(inputType.RegisterFlags), - inputType.TextureValue, - inputType.TextureDimension, - nodeId, - arrayId, - bufferId - }; + DxcHLSLRegister regD3D12; + + if (DxcReflectionError err = DxcHLSLRegister::Initialize( + regD3D12, inputType.RegisterType, ArraySizeFlat, + uint32_t(inputType.RegisterFlags), inputType.TextureValue, + inputType.TextureDimension, nodeId, arrayId, bufferId)) + return err; Refl.Registers.push_back(regD3D12); @@ -1005,23 +1062,32 @@ static void FillReflectionRegisterAt( // The name of the inner struct is $Element if 'array', otherwise equal to // register name - uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, innerType, DefaultRowMaj); + uint32_t typeId; + + if (DxcReflectionError err = + GenerateTypeInfo(typeId, ASTCtx, Refl, innerType, DefaultRowMaj)) + return err; SourceRange sourceRange = ValDesc->getSourceRange(); - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), - isListType ? "$Element" : ValDesc->getName(), nullptr, - D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, typeId, &sourceRange); + if (DxcReflectionError err = PushNextNodeId( + nodeId, Refl, SM, ASTCtx.getLangOpts(), + isListType ? "$Element" : ValDesc->getName(), nullptr, + D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, typeId, &sourceRange)) + return err; break; } } + + return DxcReflectionSuccess; } template -void RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, - DxcHLSLReflectionData &Refl, const T &Decls, - bool DefaultRowMaj, uint32_t ParentId) { +[[nodiscard]] DxcReflectionError +RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, + DxcHLSLReflectionData &Refl, const T &Decls, bool DefaultRowMaj, + uint32_t ParentId) { for (Decl *decl : Decls) { @@ -1031,38 +1097,52 @@ void RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, const std::string &name = valDecl->getName(); - uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, original, DefaultRowMaj); + uint32_t typeId; + if (DxcReflectionError err = + GenerateTypeInfo(typeId, ASTCtx, Refl, original, DefaultRowMaj)) + return err; + + uint32_t nodeId; - uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), name, decl, - D3D12_HLSL_NODE_TYPE_VARIABLE, ParentId, typeId); + if (DxcReflectionError err = + PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), name, decl, + D3D12_HLSL_NODE_TYPE_VARIABLE, ParentId, typeId)) + return err; - //Handle struct recursion + // Handle struct recursion if (RecordDecl *recordDecl = dyn_cast(decl)) { if (!recordDecl->isCompleteDefinition()) continue; - RecurseBuffer(ASTCtx, SM, Refl, recordDecl->fields(), DefaultRowMaj, nodeId); + if (DxcReflectionError err = RecurseBuffer( + ASTCtx, SM, Refl, recordDecl->fields(), DefaultRowMaj, nodeId)) + return err; } } + + return DxcReflectionSuccess; } -uint32_t RegisterBuffer(ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, - const SourceManager &SM, DeclContext *Buffer, - uint32_t NodeId, D3D_CBUFFER_TYPE Type, - bool DefaultRowMaj) { +[[nodiscard]] DxcReflectionError +RegisterBuffer(uint32_t &bufferId, ASTContext &ASTCtx, + DxcHLSLReflectionData &Refl, const SourceManager &SM, + DeclContext *Buffer, uint32_t NodeId, D3D_CBUFFER_TYPE Type, + bool DefaultRowMaj) { if (Refl.Buffers.size() >= uint32_t(-1)) - throw std::invalid_argument("Buffer id out of bounds"); + return DXC_REFLECT_ERR("Buffer id out of bounds"); - uint32_t bufferId = uint32_t(Refl.Buffers.size()); + bufferId = uint32_t(Refl.Buffers.size()); - RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), DefaultRowMaj, NodeId); + if (DxcReflectionError err = RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), + DefaultRowMaj, NodeId)) + return err; Refl.Buffers.push_back({Type, NodeId}); - return bufferId; + return DxcReflectionSuccess; } //DxilInterpolationMode.cpp but a little bit cleaned up @@ -1109,19 +1189,28 @@ static D3D_INTERPOLATION_MODE GetInterpolationMode(Decl *decl) { return modes[mask]; } -static void AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, +[[nodiscard]] static DxcReflectionError +AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, DxcHLSLReflectionData &Refl, const SourceManager &SM, uint32_t ParentNodeId, bool DefaultRowMaj) { - uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, Type, DefaultRowMaj); + uint32_t typeId; + + if (DxcReflectionError err = + GenerateTypeInfo(typeId, ASTCtx, Refl, Type, DefaultRowMaj)) + return err; - uint32_t nodeId = PushNextNodeId( - Refl, SM, ASTCtx.getLangOpts(), - Decl && dyn_cast(Decl) ? dyn_cast(Decl)->getName() - : "", - Decl, D3D12_HLSL_NODE_TYPE_PARAMETER, ParentNodeId, - uint32_t(Refl.Parameters.size())); + uint32_t nodeId; + + if (DxcReflectionError err = + PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), + Decl && dyn_cast(Decl) + ? dyn_cast(Decl)->getName() + : "", + Decl, D3D12_HLSL_NODE_TYPE_PARAMETER, ParentNodeId, + uint32_t(Refl.Parameters.size()))) + return err; D3D_INTERPOLATION_MODE interpolationMode = GetInterpolationMode(Decl); D3D_PARAMETER_FLAGS flags = D3D_PF_NONE; @@ -1140,9 +1229,11 @@ static void AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, Refl.Parameters.push_back( DxcHLSLParameter{typeId, nodeId, uint8_t(interpolationMode), uint8_t(flags)}); + + return DxcReflectionSuccess; } -static void RecursiveReflectBody( +[[nodiscard]] static DxcReflectionError RecursiveReflectBody( Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, @@ -1150,48 +1241,62 @@ static void RecursiveReflectBody( bool DefaultRowMaj, std::unordered_map &FwdDecls, const LangOptions &LangOpts, bool SkipNextCompound = false); -static void GenerateStatement( +[[nodiscard]] static DxcReflectionError GenerateStatement( ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls, const LangOptions &LangOpts, D3D12_HLSL_NODE_TYPE Type, - const VarDecl *VarDecl, Stmt *Body, Stmt *Init, - Stmt *Self, bool IfAndHasElse = false) { + const VarDecl *VarDecl, Stmt *Body, Stmt *Init, Stmt *Self, + bool IfAndHasElse = false) { uint32_t loc = uint32_t(Refl.Statements.size()); const SourceRange &sourceRange = Self->getSourceRange(); - uint32_t nodeId = PushNextNodeId(Refl, SM, LangOpts, "", nullptr, Type, - ParentNodeId, loc, &sourceRange, &FwdDecls); + uint32_t nodeId; + if (DxcReflectionError err = + PushNextNodeId(nodeId, Refl, SM, LangOpts, "", nullptr, Type, + ParentNodeId, loc, &sourceRange, &FwdDecls)) + return err; Refl.Statements.push_back(DxcHLSLStatement()); if (VarDecl) { - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, VarDecl->getType(), DefaultRowMaj); + uint32_t typeId; + if (DxcReflectionError err = GenerateTypeInfo( + typeId, ASTCtx, Refl, VarDecl->getType(), DefaultRowMaj)) + return err; const SourceRange &sourceRange = VarDecl->getSourceRange(); - PushNextNodeId(Refl, SM, LangOpts, VarDecl->getName(), VarDecl, - D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, typeId, &sourceRange, - &FwdDecls); + uint32_t nextNodeId; + if (DxcReflectionError err = + PushNextNodeId(nextNodeId, Refl, SM, LangOpts, VarDecl->getName(), + VarDecl, D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, + typeId, &sourceRange, &FwdDecls)) + return err; } uint32_t start = uint32_t(Refl.Nodes.size()); - RecursiveReflectBody(Init, ASTCtx, Diags, SM, Refl, AutoBindingSpace, - Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls, - LangOpts, true); + if (DxcReflectionError err = RecursiveReflectBody( + Init, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, + nodeId, DefaultRowMaj, FwdDecls, LangOpts, true)) + return err; - Refl.Statements[loc] = - DxcHLSLStatement(nodeId, uint32_t(Refl.Nodes.size() - start), VarDecl, IfAndHasElse); + if (DxcReflectionError err = DxcHLSLStatement::Initialize( + Refl.Statements[loc], nodeId, uint32_t(Refl.Nodes.size() - start), + VarDecl, IfAndHasElse)) + return err; - RecursiveReflectBody(Body, ASTCtx, Diags, SM, Refl, AutoBindingSpace, - Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls, - LangOpts, true); + if (DxcReflectionError err = RecursiveReflectBody( + Body, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, + nodeId, DefaultRowMaj, FwdDecls, LangOpts, true)) + return err; + + return DxcReflectionSuccess; } struct RecursiveStmtReflector : public StmtVisitor { @@ -1209,6 +1314,8 @@ struct RecursiveStmtReflector : public StmtVisitor { const LangOptions &LangOpts; bool SkipNextCompound; + DxcReflectionError LastError = DxcReflectionSuccess; + RecursiveStmtReflector(ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, @@ -1221,95 +1328,147 @@ struct RecursiveStmtReflector : public StmtVisitor { ParentNodeId(ParentNodeId), DefaultRowMaj(DefaultRowMaj), FwdDecls(FwdDecls), LangOpts(LangOpts), SkipNextCompound(SkipNextCompound) {} - void TraverseStmt(Stmt *S) { + [[nodiscard]] DxcReflectionError TraverseStmt(Stmt *S) { + + if (LastError) + return LastError; if (!S) - return; + return DxcReflectionSuccess; while (AttributedStmt *AS = dyn_cast(S)) S = AS->getSubStmt(); Visit(S); + return LastError; } void VisitStmt(const Stmt *S) {} void VisitIfStmt(IfStmt *If) { - GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, - D3D12_HLSL_NODE_TYPE_IF, If->getConditionVariable(), - If->getElse(), If->getThen(), If, If->getElse()); + + if (LastError) + return; + + LastError = GenerateStatement( + ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, + ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, + D3D12_HLSL_NODE_TYPE_IF, If->getConditionVariable(), If->getElse(), + If->getThen(), If, If->getElse()); } void VisitForStmt(ForStmt *For) { - GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, - D3D12_HLSL_NODE_TYPE_FOR, For->getConditionVariable(), - For->getBody(), For->getInit(), For); + + if (LastError) + return; + + LastError = GenerateStatement( + ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, + ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, + D3D12_HLSL_NODE_TYPE_FOR, For->getConditionVariable(), For->getBody(), + For->getInit(), For); } void VisitWhileStmt(WhileStmt *While) { - GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, - D3D12_HLSL_NODE_TYPE_WHILE, While->getConditionVariable(), - While->getBody(), nullptr, While); + + if (LastError) + return; + + LastError = GenerateStatement( + ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, + ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, + D3D12_HLSL_NODE_TYPE_WHILE, While->getConditionVariable(), + While->getBody(), nullptr, While); } void VisitDoStmt(DoStmt *Do) { + + if (LastError) + return; + const SourceRange &sourceRange = Do->getSourceRange(); - uint32_t scopeNode = - PushNextNodeId(Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_DO, - ParentNodeId, 0, &sourceRange, &FwdDecls); + uint32_t scopeNode; + if (DxcReflectionError err = PushNextNodeId( + scopeNode, Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_DO, + ParentNodeId, 0, &sourceRange, &FwdDecls)) { + LastError = err; + return; + } - RecursiveReflectBody(Do->getBody(), ASTCtx, Diags, SM, Refl, - AutoBindingSpace, Depth + 1, Features, scopeNode, - DefaultRowMaj, FwdDecls, LangOpts, true); + LastError = RecursiveReflectBody( + Do->getBody(), ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, scopeNode, DefaultRowMaj, FwdDecls, LangOpts, true); } void VisitSwitchStmt(SwitchStmt *Switch) { - GenerateStatement(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, - Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, - D3D12_HLSL_NODE_TYPE_SWITCH, - Switch->getConditionVariable(), Switch->getBody(), - nullptr, Switch); + + if (LastError) + return; + + LastError = GenerateStatement( + ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, + ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, + D3D12_HLSL_NODE_TYPE_SWITCH, Switch->getConditionVariable(), + Switch->getBody(), nullptr, Switch); } void VisitCompoundStmt(CompoundStmt *C) { + if (LastError) + return; + const SourceRange &sourceRange = C->getSourceRange(); - uint32_t scopeNode = - SkipNextCompound - ? ParentNodeId - : PushNextNodeId(Refl, SM, LangOpts, "", nullptr, + uint32_t scopeNode = ParentNodeId; + + if (!SkipNextCompound) + if (DxcReflectionError err = + PushNextNodeId(scopeNode, Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_SCOPE, ParentNodeId, 0, - &sourceRange, &FwdDecls); + &sourceRange, &FwdDecls)) { + LastError = err; + return; + } for (Stmt *child : C->body()) - RecursiveReflectBody(child, ASTCtx, Diags, SM, Refl, AutoBindingSpace, - Depth + 1, Features, scopeNode, DefaultRowMaj, - FwdDecls, LangOpts); + if (DxcReflectionError err = RecursiveReflectBody( + child, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, + Features, scopeNode, DefaultRowMaj, FwdDecls, LangOpts)) { + LastError = err; + return; + } } void VisitDeclStmt(DeclStmt *DS) { + + if (LastError) + return; + for (Decl *D : DS->decls()) { if (VarDecl *varDecl = dyn_cast(D)) { - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, varDecl->getType(), DefaultRowMaj); + uint32_t typeId; + if (DxcReflectionError err = GenerateTypeInfo( + typeId, ASTCtx, Refl, varDecl->getType(), DefaultRowMaj)) { + LastError = err; + return; + } const SourceRange &sourceRange = varDecl->getSourceRange(); - PushNextNodeId(Refl, SM, LangOpts, varDecl->getName(), varDecl, - D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId, - &sourceRange, &FwdDecls); + uint32_t nodeId; + if (DxcReflectionError err = PushNextNodeId(nodeId, Refl, SM, LangOpts, varDecl->getName(), varDecl, + D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId, &sourceRange, &FwdDecls)) { + LastError = err; + return; + } } } } }; -static void +[[nodiscard]] static DxcReflectionError RecursiveReflectBody(Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, @@ -1320,10 +1479,10 @@ RecursiveReflectBody(Stmt *Statement, ASTContext &ASTCtx, RecursiveStmtReflector Reflector(ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth, Features, ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, SkipNextCompound); - Reflector.TraverseStmt(Statement); + return Reflector.TraverseStmt(Statement); } -static void +[[nodiscard]] static DxcReflectionError RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, @@ -1344,14 +1503,20 @@ class RecursiveReflector : public DeclVisitor { uint32_t ParentNodeId; bool DefaultRowMaj; std::unordered_map &FwdDecls; + + DxcReflectionError LastError = DxcReflectionSuccess; - void PushVariable(ValueDecl *VD, D3D12_HLSL_NODE_TYPE NodeType) { + [[nodiscard]] DxcReflectionError PushVariable(ValueDecl *VD, + D3D12_HLSL_NODE_TYPE NodeType) { - uint32_t typeId = - GenerateTypeInfo(ASTCtx, Refl, VD->getType(), DefaultRowMaj); + uint32_t typeId; + if (DxcReflectionError err = GenerateTypeInfo(typeId, ASTCtx, Refl, + VD->getType(), DefaultRowMaj)) + return err; - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), VD->getName(), VD, NodeType, - ParentNodeId, typeId); + uint32_t nodeId; + return PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), VD->getName(), + VD, NodeType, ParentNodeId, typeId); } public: @@ -1367,50 +1532,78 @@ class RecursiveReflector : public DeclVisitor { ParentNodeId(ParentNodeId), DefaultRowMaj(DefaultRowMaj), FwdDecls(FwdDecls){} - void TraverseDeclContext() { + [[nodiscard]] DxcReflectionError TraverseDeclContext() { + + if (LastError) + return LastError; for (Decl *it : Ctx.decls()) { SourceLocation Loc = it->getLocation(); - if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) //TODO: We might want to include these for a more complete picture. + if (Loc.isInvalid() || + SM.isInSystemHeader(Loc)) // TODO: We might want to include these for + // a more complete picture. continue; Visit(it); + + if (LastError) + return LastError; } + + return DxcReflectionSuccess; } void VisitDecl(Decl *D) {} void VisitHLSLBufferDecl(HLSLBufferDecl *CB) { + if (LastError) + return; + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) return; if (Depth != 0) return; - uint32_t nodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), CB->getName(), CB, - D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, - uint32_t(Refl.Registers.size())); + uint32_t nodeId; + + if (DxcReflectionError err = + PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), + CB->getName(), CB, D3D12_HLSL_NODE_TYPE_REGISTER, + ParentNodeId, uint32_t(Refl.Registers.size()))) { + LastError = err; + return; + } - uint32_t bufferId = RegisterBuffer(ASTCtx, Refl, SM, CB, nodeId, - D3D_CT_CBUFFER, DefaultRowMaj); + uint32_t bufferId; - DxcHLSLRegister regD3D12 = {D3D_SIT_CBUFFER, - 1, - uint32_t(D3D_SIF_USERPACKED), - D3D_RESOURCE_RETURN_TYPE(0), - D3D_SRV_DIMENSION_UNKNOWN, - nodeId, - uint32_t(-1), - bufferId}; + if (DxcReflectionError err = + RegisterBuffer(bufferId, ASTCtx, Refl, SM, CB, nodeId, + D3D_CT_CBUFFER, DefaultRowMaj)) { + LastError = err; + return; + } + + DxcHLSLRegister regD3D12; + + if (DxcReflectionError err = DxcHLSLRegister::Initialize( + regD3D12, D3D_SIT_CBUFFER, 1, uint32_t(D3D_SIF_USERPACKED), + D3D_RESOURCE_RETURN_TYPE(0), D3D_SRV_DIMENSION_UNKNOWN, nodeId, + uint32_t(-1), bufferId)) { + LastError = err; + return; + } Refl.Registers.push_back(regD3D12); } void VisitFunctionDecl(FunctionDecl *FD) { + if (LastError) + return; + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS)) return; @@ -1419,27 +1612,41 @@ class RecursiveReflector : public DeclVisitor { const FunctionDecl *definition = nullptr; - uint32_t nodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), FD->getName(), FD, - D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, - uint32_t(Refl.Functions.size()), nullptr, &FwdDecls); + uint32_t nodeId; + if (DxcReflectionError err = PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), FD->getName(), FD, + D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, + uint32_t(Refl.Functions.size()), nullptr, &FwdDecls)) { + LastError = err; + return; + } if (nodeId == uint32_t(-1)) // Duplicate fwd definition return; bool hasDefinition = FD->hasBody(definition); - DxcHLSLFunction func = {nodeId, FD->getNumParams(), - !FD->getReturnType().getTypePtr()->isVoidType(), - hasDefinition}; + DxcHLSLFunction func; + + if (DxcReflectionError err = DxcHLSLFunction::Initialize(func, nodeId, FD->getNumParams(), + !FD->getReturnType().getTypePtr()->isVoidType(), hasDefinition)) { + LastError = err; + return; + } for (uint32_t i = 0; i < func.GetNumParameters(); ++i) - AddFunctionParameter(ASTCtx, FD->getParamDecl(i)->getType(), - FD->getParamDecl(i), Refl, SM, nodeId, - DefaultRowMaj); + if (DxcReflectionError err = AddFunctionParameter( + ASTCtx, FD->getParamDecl(i)->getType(), FD->getParamDecl(i), Refl, + SM, nodeId, DefaultRowMaj)) { + LastError = err; + return; + } if (func.HasReturn()) - AddFunctionParameter(ASTCtx, FD->getReturnType(), nullptr, Refl, SM, - nodeId, DefaultRowMaj); + if (DxcReflectionError err = + AddFunctionParameter(ASTCtx, FD->getReturnType(), nullptr, Refl, + SM, nodeId, DefaultRowMaj)) { + LastError = err; + return; + } Refl.Functions.push_back(std::move(func)); @@ -1452,87 +1659,118 @@ class RecursiveReflector : public DeclVisitor { if (!subStmt) continue; - RecursiveReflectBody(subStmt, ASTCtx, Diags, SM, Refl, AutoBindingSpace, + if (DxcReflectionError err = RecursiveReflectBody(subStmt, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth, Features, nodeId, DefaultRowMaj, FwdDecls, - ASTCtx.getLangOpts()); + ASTCtx.getLangOpts())) { + LastError = err; + return; + } } } } void VisitEnumDecl(EnumDecl *ED) { - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - return; + if (LastError) + return; - uint32_t nodeId = PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), ED->getName(), ED, - D3D12_HLSL_NODE_TYPE_ENUM, ParentNodeId, - uint32_t(Refl.Enums.size()), nullptr, &FwdDecls); + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + return; - if (nodeId == uint32_t(-1)) // Duplicate fwd definition - return; + uint32_t nodeId; + + if (DxcReflectionError err = PushNextNodeId( + nodeId, Refl, SM, ASTCtx.getLangOpts(), ED->getName(), ED, + D3D12_HLSL_NODE_TYPE_ENUM, ParentNodeId, + uint32_t(Refl.Enums.size()), nullptr, &FwdDecls)) { + LastError = err; + return; + } + + if (nodeId == uint32_t(-1)) // Duplicate fwd definition + return; - for (EnumConstantDecl *enumValue : ED->enumerators()) { + for (EnumConstantDecl *enumValue : ED->enumerators()) { - uint32_t childNodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), enumValue->getName(), - enumValue, D3D12_HLSL_NODE_TYPE_ENUM_VALUE, nodeId, - uint32_t(Refl.EnumValues.size())); + uint32_t childNodeId; - Refl.EnumValues.push_back( - {enumValue->getInitVal().getSExtValue(), childNodeId}); + if (DxcReflectionError err = PushNextNodeId( + childNodeId, Refl, SM, ASTCtx.getLangOpts(), enumValue->getName(), + enumValue, D3D12_HLSL_NODE_TYPE_ENUM_VALUE, nodeId, + uint32_t(Refl.EnumValues.size()))) { + LastError = err; + return; } - if (Refl.EnumValues.size() >= uint32_t(1 << 30)) - throw std::invalid_argument("Enum values overflow"); + Refl.EnumValues.push_back( + {enumValue->getInitVal().getSExtValue(), childNodeId}); + } - QualType enumType = ED->getIntegerType(); - QualType desugared = enumType.getDesugaredType(ASTCtx); - const auto &semantics = ASTCtx.getTypeInfo(desugared); + if (Refl.EnumValues.size() >= uint32_t(1 << 30)) + throw std::invalid_argument("Enum values overflow"); - D3D12_HLSL_ENUM_TYPE type; + QualType enumType = ED->getIntegerType(); + QualType desugared = enumType.getDesugaredType(ASTCtx); + const auto &semantics = ASTCtx.getTypeInfo(desugared); - switch (semantics.Width) { + D3D12_HLSL_ENUM_TYPE type; - default: - case 32: - type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT - : D3D12_HLSL_ENUM_TYPE_INT; - break; + switch (semantics.Width) { - case 16: - type = desugared->isUnsignedIntegerType() - ? D3D12_HLSL_ENUM_TYPE_UINT16_T - : D3D12_HLSL_ENUM_TYPE_INT16_T; - break; + default: + case 32: + type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT + : D3D12_HLSL_ENUM_TYPE_INT; + break; - case 64: - type = desugared->isUnsignedIntegerType() - ? D3D12_HLSL_ENUM_TYPE_UINT64_T - : D3D12_HLSL_ENUM_TYPE_INT64_T; - break; - } + case 16: + type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT16_T + : D3D12_HLSL_ENUM_TYPE_INT16_T; + break; - Refl.Enums.push_back({nodeId, type}); + case 64: + type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT64_T + : D3D12_HLSL_ENUM_TYPE_INT64_T; + break; + } + + Refl.Enums.push_back({nodeId, type}); } void VisitTypedefDecl(TypedefDecl *TD) { + if (LastError) + return; + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) return; - uint32_t typeId = GenerateTypeInfo(ASTCtx, Refl, TD->getUnderlyingType(), - DefaultRowMaj); + uint32_t typeId; + if (DxcReflectionError err = GenerateTypeInfo( + typeId, ASTCtx, Refl, TD->getUnderlyingType(), DefaultRowMaj)) { + LastError = err; + return; + } - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), TD->getName(), TD, - D3D12_HLSL_NODE_TYPE_TYPEDEF, ParentNodeId, typeId); + uint32_t nodeId; + LastError = PushNextNodeId( + nodeId, Refl, SM, ASTCtx.getLangOpts(), TD->getName(), TD, + D3D12_HLSL_NODE_TYPE_TYPEDEF, ParentNodeId, typeId); } void VisitFieldDecl(FieldDecl *FD) { - PushVariable(FD, D3D12_HLSL_NODE_TYPE_VARIABLE); + + if (LastError) + return; + + LastError = PushVariable(FD, D3D12_HLSL_NODE_TYPE_VARIABLE); } void VisitValueDecl(ValueDecl *VD) { + if (LastError) + return; + if (isa(VD)) // Skip parameters, already handled explicitly return; @@ -1543,7 +1781,7 @@ class RecursiveReflector : public DeclVisitor { if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) return; - PushVariable(VD, D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE); + LastError = PushVariable(VD, D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE); return; } @@ -1552,7 +1790,7 @@ class RecursiveReflector : public DeclVisitor { if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) return; - PushVariable(VD, D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE); + LastError = PushVariable(VD, D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE); return; } @@ -1574,7 +1812,7 @@ class RecursiveReflector : public DeclVisitor { if (varDecl && (Depth == 0 || Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES)) { - PushVariable(VD, D3D12_HLSL_NODE_TYPE_VARIABLE); + LastError = PushVariable(VD, D3D12_HLSL_NODE_TYPE_VARIABLE); } return; @@ -1583,13 +1821,16 @@ class RecursiveReflector : public DeclVisitor { if (Depth != 0 || !(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) return; - FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, VD, + LastError = FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, VD, arrayElem, Refl, AutoBindingSpace, ParentNodeId, DefaultRowMaj); } void VisitRecordDecl(RecordDecl *RD) { + if (LastError) + return; + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) return; @@ -1617,38 +1858,57 @@ class RecursiveReflector : public DeclVisitor { uint32_t typeId = 0; if (isDefinition) - typeId = GenerateTypeInfo( - ASTCtx, Refl, RD->getASTContext().getRecordType(RD), DefaultRowMaj); + if (DxcReflectionError err = GenerateTypeInfo( + typeId, ASTCtx, Refl, RD->getASTContext().getRecordType(RD), + DefaultRowMaj)) { + LastError = err; + return; + } - uint32_t self = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), RD->getName(), RD, - type, ParentNodeId, typeId, nullptr, &FwdDecls); + uint32_t self; + if (DxcReflectionError err = PushNextNodeId( + self, Refl, SM, ASTCtx.getLangOpts(), RD->getName(), RD, type, + ParentNodeId, typeId, nullptr, &FwdDecls)) { + LastError = err; + return; + } if (self == uint32_t(-1)) // Duplicate fwd definition return; if (isDefinition) - RecursiveReflectHLSL(*RD, ASTCtx, Diags, SM, Refl, AutoBindingSpace, - Depth + 1, Features, self, DefaultRowMaj, - FwdDecls); + LastError = RecursiveReflectHLSL(*RD, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, + self, DefaultRowMaj, FwdDecls); } } void VisitNamespaceDecl(NamespaceDecl *ND) { + if (LastError) + return; + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES)) return; - uint32_t nodeId = - PushNextNodeId(Refl, SM, ASTCtx.getLangOpts(), ND->getName(), ND, - D3D12_HLSL_NODE_TYPE_NAMESPACE, ParentNodeId, 0); + uint32_t nodeId; + if (DxcReflectionError err = PushNextNodeId( + nodeId, Refl, SM, ASTCtx.getLangOpts(), ND->getName(), ND, + D3D12_HLSL_NODE_TYPE_NAMESPACE, ParentNodeId, 0)) { + LastError = err; + return; + } - RecursiveReflectHLSL(*ND, ASTCtx, Diags, SM, Refl, AutoBindingSpace, - Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls); + LastError = RecursiveReflectHLSL(*ND, ASTCtx, Diags, SM, Refl, + AutoBindingSpace, Depth + 1, Features, + nodeId, DefaultRowMaj, FwdDecls); } /*void VisitTypeAliasDecl(TypeAliasDecl *TAD) { + if (LastError) + return; + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) return; @@ -1656,7 +1916,7 @@ class RecursiveReflector : public DeclVisitor { }*/ }; -static void +[[nodiscard]] static DxcReflectionError RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, @@ -1666,10 +1926,11 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, RecursiveReflector Reflector(Ctx, ASTCtx, SM, Diags, Refl, AutoBindingSpace, Depth, Features, ParentNodeId, DefaultRowMaj, FwdDecls); - Reflector.TraverseDeclContext(); + return Reflector.TraverseDeclContext(); } -bool DxcHLSLReflectionDataFromAST(DxcHLSLReflectionData &Result, +[[nodiscard]] DxcReflectionError DxcHLSLReflectionDataFromAST( + DxcHLSLReflectionData &Result, CompilerInstance &Compiler, TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, @@ -1685,24 +1946,38 @@ bool DxcHLSLReflectionDataFromAST(DxcHLSLReflectionData &Result, if (Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { Result.Strings.push_back(""); Result.StringsToId[""] = 0; - Result.NodeSymbols.push_back(DxcHLSLNodeSymbol(0, 0, 0, 0, 0, 0)); + Result.NodeSymbols.push_back({}); + + if (DxcReflectionError err = DxcHLSLNodeSymbol::Initialize( + Result.NodeSymbols[0], 0, 0, 0, 0, 0, 0)) { + llvm::errs() + << "DxcHLSLReflectionDataFromAST: Failed to add root symbol: " << err; + Result = {}; + return err; + } } - Result.Nodes.push_back(DxcHLSLNode{D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, - 0, 0, 0xFFFF, 0, uint16_t(-1)}); - - try { + Result.Nodes.push_back({}); + if (DxcReflectionError err = DxcHLSLNode::Initialize( + Result.Nodes[0], D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, 0, 0, + 0xFFFF, 0, uint16_t(-1))) { + llvm::errs() << "DxcHLSLReflectionDataFromAST: Failed to add root node: " + << err; + Result = {}; + return err; + } - std::unordered_map fwdDecls; - RecursiveReflectHLSL(Ctx, Compiler.getASTContext(), Diags, SM, Result, - AutoBindingSpace, 0, Features, 0, DefaultRowMaj, - fwdDecls); - return true; + std::unordered_map fwdDecls; - } catch (const std::invalid_argument &arg) { - llvm::errs() << "DxcHLSLReflectionData::Initialize: Failed " << arg.what(); - return false; + if (DxcReflectionError err = RecursiveReflectHLSL( + Ctx, Compiler.getASTContext(), Diags, SM, Result, AutoBindingSpace, 0, + Features, 0, DefaultRowMaj, fwdDecls)) { + llvm::errs() << "DxcHLSLReflectionDataFromAST: Failed: " << err; + Result = {}; + return err; } + + return DxcReflectionSuccess; } } // namespace hlsl diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 992313c551..3391e64c4f 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -51,7 +51,7 @@ using namespace hlsl; namespace hlsl { -bool DxcHLSLReflectionDataFromAST(DxcHLSLReflectionData &Result, +[[nodiscard]] DxcReflectionError DxcHLSLReflectionDataFromAST(DxcHLSLReflectionData &Result, clang::CompilerInstance &Compiler, clang::TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, @@ -256,7 +256,7 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { ZeroMemoryToOut(&m_ArrayDescDisplay); InitializeArray(Data, m_ArrayDescUnderlying, m_ElementsUnderlying, - type.UnderlyingArray); + type.GetUnderlyingArray()); bool hasNames = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -288,8 +288,8 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { } } - if (type.BaseClass != uint32_t(-1)) - m_pBaseClass = &Types[type.BaseClass]; + if (type.GetBaseClass() != uint32_t(-1)) + m_pBaseClass = &Types[type.GetBaseClass()]; uint32_t interfaceCount = type.GetInterfaceCount(); @@ -309,10 +309,10 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { *pDesc = D3D12_SHADER_TYPE_DESC { - (D3D_SHADER_VARIABLE_CLASS) type.Class, - (D3D_SHADER_VARIABLE_TYPE) type.Type, - type.Rows, - type.Columns, + type.GetClass(), + type.GetType(), + type.GetRows(), + type.GetColumns(), m_ElementsUnderlying, uint32_t(m_MemberTypes.size()), @@ -423,7 +423,7 @@ class CHLSLFunctionParameter final : public ID3D12FunctionParameterReflection { LPCSTR name = m_Data->Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - ? m_Data->Strings[m_Data->NodeSymbols[m_NodeId].NameId].c_str() + ? m_Data->Strings[m_Data->NodeSymbols[m_NodeId].GetNameId()].c_str() : ""; const DxcHLSLParameter ¶m = m_Data->Parameters[node.GetLocalId()]; @@ -432,10 +432,10 @@ class CHLSLFunctionParameter final : public ID3D12FunctionParameterReflection { *pDesc = D3D12_PARAMETER_DESC{name, semanticName, - D3D_SHADER_VARIABLE_TYPE(type.Type), - D3D_SHADER_VARIABLE_CLASS(type.Class), - type.Rows, - type.Columns, + type.GetType(), + type.GetClass(), + type.GetRows(), + type.GetColumns(), D3D_INTERPOLATION_MODE(param.InterpolationMode), D3D_PARAMETER_FLAGS(param.Flags)}; @@ -525,15 +525,15 @@ class CHLSLReflectionConstantBuffer final if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { - m_ReflectionName = Data.Strings[Data.NodeSymbols[NodeId].NameId]; + m_ReflectionName = Data.Strings[Data.NodeSymbols[NodeId].GetNameId()]; - bool isCBuffer = reg.Type == D3D_SIT_CBUFFER; + bool isCBuffer = reg.GetType() == D3D_SIT_CBUFFER; if (m_ReflectionName.size() && !isCBuffer) { - uint32_t arrayDims = reg.ArrayId != uint32_t(-1) - ? Data.Arrays[reg.ArrayId].ArrayElem() - : (reg.BindCount > 1 ? 1 : 0); + uint32_t arrayDims = reg.GetArrayId() != uint32_t(-1) + ? Data.Arrays[reg.GetArrayId()].ArrayElem() + : (reg.GetBindCount() > 1 ? 1 : 0); for (unsigned i = 0; i < arrayDims; ++i) m_ReflectionName += "[0]"; @@ -545,7 +545,7 @@ class CHLSLReflectionConstantBuffer final m_Data = &Data; m_ChildCount = uint32_t(children.size()); - m_BufferType = m_Data->Buffers[reg.BufferId].Type; + m_BufferType = m_Data->Buffers[reg.GetBufferId()].Type; m_VariablesByName.clear(); m_Variables.resize(children.size()); @@ -557,7 +557,7 @@ class CHLSLReflectionConstantBuffer final std::string name; if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) - name = Data.Strings[Data.NodeSymbols[childId].NameId]; + name = Data.Strings[Data.NodeSymbols[childId].GetNameId()]; uint32_t typeId = Data.Nodes[childId].GetLocalId(); @@ -593,7 +593,7 @@ class CHLSLReflectionConstantBuffer final std::string name; if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) - name = Data.Strings[Data.NodeSymbols[childId].NameId]; + name = Data.Strings[Data.NodeSymbols[childId].GetNameId()]; uint32_t typeId = Data.Nodes[childId].GetLocalId(); @@ -743,7 +743,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (hasSymbols) NameToNonFwdIds[int(type)] - [Data.Strings[Data.NodeSymbols[i].NameId]] = typeId; + [Data.Strings[Data.NodeSymbols[i].GetNameId()]] = + typeId; break; } @@ -852,14 +853,15 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { LPCSTR name = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - ? Data.Strings[Data.NodeSymbols[reg.NodeId].NameId].c_str() + ? Data.Strings[Data.NodeSymbols[reg.GetNodeId()].GetNameId()] + .c_str() : ""; - if (reg.BindCount > 1) { + if (reg.GetBindCount() > 1) { - if (reg.ArrayId != uint32_t(-1)) { + if (reg.GetArrayId() != uint32_t(-1)) { - const DxcHLSLArray &arr = Data.Arrays[reg.ArrayId]; + const DxcHLSLArray &arr = Data.Arrays[reg.GetArrayId()]; pDesc->ArrayInfo.ArrayDims = arr.ArrayElem(); @@ -870,21 +872,21 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { else { pDesc->ArrayInfo.ArrayDims = 1; - pDesc->ArrayInfo.ArrayLengths[0] = reg.BindCount; + pDesc->ArrayInfo.ArrayLengths[0] = reg.GetBindCount(); } } pDesc->Desc = D3D12_SHADER_INPUT_BIND_DESC{ - name, D3D_SHADER_INPUT_TYPE(reg.Type), + name, reg.GetType(), uint32_t(-1), // Invalid bindPoint, depending on backend we might // want to change it - reg.BindCount, + reg.GetBindCount(), - reg.uFlags, D3D_RESOURCE_RETURN_TYPE(reg.ReturnType), - D3D_SRV_DIMENSION(reg.Dimension), + reg.GetFlags(), reg.GetReturnType(), + reg.GetDimension(), uint32_t(-1), // Also no valid data depending on backend uint32_t(-1), // Invalid space (see bindPoint ^) - reg.NodeId}; + reg.GetNodeId()}; return S_OK; } @@ -902,7 +904,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { LPCSTR name = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - ? Data.Strings[Data.NodeSymbols[enm.NodeId].NameId].c_str() + ? Data.Strings[Data.NodeSymbols[enm.NodeId].GetNameId()].c_str() : ""; *pDesc = D3D12_HLSL_ENUM_DESC{ @@ -928,7 +930,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { LPCSTR name = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - ? Data.Strings[Data.NodeSymbols[enm.NodeId].NameId].c_str() + ? Data.Strings[Data.NodeSymbols[enm.NodeId].GetNameId()].c_str() : ""; const DxcHLSLNode &node = Data.Nodes[enm.NodeId + 1 + ValueIndex]; @@ -977,7 +979,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { LPCSTR name = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - ? Data.Strings[Data.NodeSymbols[func.NodeId].NameId].c_str() + ? Data.Strings[Data.NodeSymbols[func.GetNodeId()].GetNameId()] + .c_str() : ""; *pDesc = D3D12_HLSL_FUNCTION_DESC{name, func.GetNumParameters(), @@ -995,7 +998,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { return E_INVALIDARG; LPCSTR name = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - ? Data.Strings[Data.NodeSymbols[NodeId].NameId].c_str() + ? Data.Strings[Data.NodeSymbols[NodeId].GetNameId()].c_str() : ""; const DxcHLSLNode &node = Data.Nodes[NodeId]; @@ -1101,7 +1104,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { return nullptr; uint32_t parameterId = - NodeToParameterId[func.NodeId + 1 + func.GetNumParameters()]; + NodeToParameterId[func.GetNodeId() + 1 + func.GetNumParameters()]; return &FunctionParameters[parameterId]; } @@ -1109,7 +1112,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (uint32_t(ParameterIndex) >= func.GetNumParameters()) return nullptr; - uint32_t parameterId = NodeToParameterId[func.NodeId + 1 + ParameterIndex]; + uint32_t parameterId = + NodeToParameterId[func.GetNodeId() + 1 + ParameterIndex]; return &FunctionParameters[parameterId]; } @@ -1166,8 +1170,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { const DxcHLSLNodeSymbol &nodeSymbol = Data.NodeSymbols[NodeId]; *pDesc = D3D12_HLSL_NODE_SYMBOL{ - Data.Strings[Data.Sources[nodeSymbol.FileSourceId]].c_str(), - nodeSymbol.GetSourceLineStart(), nodeSymbol.SourceLineCount, + Data.Strings[Data.Sources[nodeSymbol.GetFileSourceId()]].c_str(), + nodeSymbol.GetSourceLineStart(), nodeSymbol.GetSourceLineCount(), nodeSymbol.GetSourceColumnStart(), nodeSymbol.GetSourceColumnEnd()}; return S_OK; @@ -1593,10 +1597,10 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, DxcHLSLReflectionData refl; - if (!DxcHLSLReflectionDataFromAST(refl, astHelper.compiler, *astHelper.tu, + if (DxcReflectionError err = DxcHLSLReflectionDataFromAST(refl, astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, reflectMask, opts.DefaultRowMajor)) - throw std::exception("refl.Initialize failed"); + throw std::exception(("refl.Initialize failed " + std::string(err)).c_str()); //TODO: Debug From bb6c8df058297fc13471b6530e00093196abee63 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 29 Oct 2025 23:53:49 +0100 Subject: [PATCH 066/126] Removed all throws from AST traversal. Only need to fix the ones in deserialization --- include/dxc/DxcReflection/DxcReflection.h | 7 +- .../tools/dxcreflection/DxcReflection.cpp | 38 +++++--- .../tools/libclang/dxcreflection_from_ast.cpp | 90 ++++++++++++++----- tools/clang/tools/libclang/dxcreflector.cpp | 22 +++-- 4 files changed, 113 insertions(+), 44 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 57e6d53854..f7d30e3f56 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -794,11 +794,14 @@ struct DxcHLSLReflectionData { std::vector NodeIdToFullyResolved; std::unordered_map FullyResolvedToMemberId; - uint32_t RegisterString(const std::string &Name, bool IsNonDebug); + [[nodiscard]] DxcReflectionError + RegisterString(uint32_t &StringId, const std::string &Name, bool IsNonDebug); + [[nodiscard]] DxcReflectionError PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, const std::vector &ArraySize); - void RegisterTypeList(const std::vector &TypeIds, uint32_t &Offset, + [[nodiscard]] DxcReflectionError + RegisterTypeList(const std::vector &TypeIds, uint32_t &Offset, uint8_t &Len); static D3D_CBUFFER_TYPE GetBufferType(uint8_t Type); diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index d796b67978..05f1d0ba61 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -16,42 +16,50 @@ namespace hlsl { -uint32_t DxcHLSLReflectionData::RegisterString(const std::string &Name, +[[nodiscard]] DxcReflectionError DxcHLSLReflectionData::RegisterString( + uint32_t &StringId, + const std::string &Name, bool IsNonDebug) { if (Name.size() >= 32768) - throw std::invalid_argument("Strings are limited to 32767"); + return DXC_REFLECT_ERR("Strings are limited to 32767"); if (IsNonDebug) { if (StringsNonDebug.size() >= uint32_t(-1)) - throw std::invalid_argument("Strings overflow"); + return DXC_REFLECT_ERR("Strings overflow"); auto it = StringsToIdNonDebug.find(Name); - if (it != StringsToIdNonDebug.end()) - return it->second; + if (it != StringsToIdNonDebug.end()) { + StringId = it->second; + return DxcReflectionSuccess; + } uint32_t stringId = uint32_t(StringsNonDebug.size()); StringsNonDebug.push_back(Name); StringsToIdNonDebug[Name] = stringId; - return stringId; + StringId = stringId; + return DxcReflectionSuccess; } if (Strings.size() >= uint32_t(-1)) - throw std::invalid_argument("Strings overflow"); + return DXC_REFLECT_ERR("Strings overflow"); auto it = StringsToId.find(Name); - if (it != StringsToId.end()) - return it->second; + if (it != StringsToId.end()) { + StringId = it->second; + return DxcReflectionSuccess; + } uint32_t stringId = uint32_t(Strings.size()); Strings.push_back(Name); StringsToId[Name] = stringId; - return stringId; + StringId = stringId; + return DxcReflectionSuccess; } [[nodiscard]] DxcReflectionError @@ -103,14 +111,15 @@ DxcHLSLReflectionData::PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, return DxcReflectionSuccess; } -void DxcHLSLReflectionData::RegisterTypeList( +[[nodiscard]] DxcReflectionError +DxcHLSLReflectionData::RegisterTypeList( const std::vector &TypeIds, uint32_t &Offset, uint8_t &Len) { if (TypeIds.empty()) - return; + return DxcReflectionSuccess; if (TypeIds.size() >= uint8_t(-1)) - throw std::invalid_argument("Only allowing 256 types in a type list"); + return DXC_REFLECT_ERR("Only allowing 256 types in a type list"); uint32_t i = 0; uint32_t j = uint32_t(TypeList.size()); @@ -143,7 +152,7 @@ void DxcHLSLReflectionData::RegisterTypeList( uint32_t oldSiz = uint32_t(TypeList.size()); if (oldSiz + TypeIds.size() >= (1u << 24)) - throw std::invalid_argument("Only allowing 16Mi total interfaces"); + return DXC_REFLECT_ERR("Only allowing 16Mi total interfaces"); TypeList.resize(oldSiz + TypeIds.size()); @@ -154,6 +163,7 @@ void DxcHLSLReflectionData::RegisterTypeList( } Len = uint8_t(TypeIds.size()); + return DxcReflectionSuccess; } //TODO: Debug print code diff --git a/tools/clang/tools/libclang/dxcreflection_from_ast.cpp b/tools/clang/tools/libclang/dxcreflection_from_ast.cpp index 1f5d18ff3d..0e741dc465 100644 --- a/tools/clang/tools/libclang/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/libclang/dxcreflection_from_ast.cpp @@ -55,9 +55,15 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage Refl.Annotations.push_back({}); + uint32_t stringId; + + if (DxcReflectionError err = + Refl.RegisterString(stringId, annotate->getAnnotation().str(), true)) + return err; + if (DxcReflectionError err = DxcHLSLAnnotation::Initialize( Refl.Annotations.back(), - Refl.RegisterString(annotate->getAnnotation().str(), true), + stringId, false)) return err; @@ -74,10 +80,15 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage Refl.Annotations.push_back({}); + uint32_t stringId; + + if (DxcReflectionError err = Refl.RegisterString( + stringId, "shader(\"" + shaderAttr->getStage().str() + "\")", true)) + return err; + if (DxcReflectionError err = DxcHLSLAnnotation::Initialize( Refl.Annotations.back(), - Refl.RegisterString( - "shader(\"" + shaderAttr->getStage().str() + "\")", true), + stringId, true)) return err; @@ -95,8 +106,16 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage for (auto It = UA.begin(), E = UA.end(); It != E; ++It) if ((*It)->getKind() == hlsl::UnusualAnnotation::UA_SemanticDecl) { - semanticId = Refl.RegisterString( - cast(*It)->SemanticName.str(), true); + + uint32_t semanticId32; + + if (DxcReflectionError err = Refl.RegisterString( + semanticId32, + cast(*It)->SemanticName.str(), + true)) + return err; + + semanticId = uint16_t(semanticId32); } } } @@ -194,8 +213,15 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage uint32_t i; if (it == Refl.StringToSourceId.end()) { - i = (uint32_t)Refl.Sources.size(); - Refl.Sources.push_back(Refl.RegisterString(fileName, false)); + + i = uint32_t(Refl.Sources.size()); + uint32_t stringId; + + if (DxcReflectionError err = + Refl.RegisterString(stringId, fileName, false)) + return err; + + Refl.Sources.push_back(stringId); Refl.StringToSourceId[fileName] = i; } @@ -226,7 +252,11 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage } } - uint32_t nameId = Refl.RegisterString(UnqualifiedName, false); + uint32_t nameId; + + if (DxcReflectionError err = + Refl.RegisterString(nameId, UnqualifiedName, false)) + return err; Refl.NodeSymbols.push_back({}); @@ -718,8 +748,12 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, if (innerTypeName.size()) { - uint32_t nameId = hasSymbols ? Refl.RegisterString(innerTypeName, false) - : uint32_t(-1); + uint32_t nameId = uint32_t(-1); + + if (hasSymbols) + if (DxcReflectionError err = + Refl.RegisterString(nameId, innerTypeName, false)) + return err; uint32_t typeId; @@ -787,11 +821,15 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, std::string name = fieldDecl->getName(); - uint32_t nameId = - hasSymbols ? Refl.RegisterString(name, false) : uint32_t(-1); + uint32_t nameId = uint32_t(-1); + + if (hasSymbols) { + + if (DxcReflectionError err = Refl.RegisterString(nameId, name, false)) + return err; - if (hasSymbols) Refl.MemberNameIds.push_back(nameId); + } ++membersCount; } @@ -954,7 +992,9 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, uint32_t interfaceOffset = 0; uint8_t interfaceCount = 0; - Refl.RegisterTypeList(interfaces, interfaceOffset, interfaceCount); + if (DxcReflectionError err = + Refl.RegisterTypeList(interfaces, interfaceOffset, interfaceCount)) + return err; DxcHLSLType hlslType; if (DxcReflectionError err = DxcHLSLType::Initialize( @@ -963,11 +1003,19 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, interfaceCount)) return err; - uint32_t displayNameId = - hasSymbols ? Refl.RegisterString(displayName, false) : uint32_t(-1); + uint32_t displayNameId = uint32_t(-1); + uint32_t underlyingNameId = uint32_t(-1); - uint32_t underlyingNameId = - hasSymbols ? Refl.RegisterString(underlyingName, false) : uint32_t(-1); + if (hasSymbols) { + + if (DxcReflectionError err = + Refl.RegisterString(displayNameId, displayName, false)) + return err; + + if (DxcReflectionError err = + Refl.RegisterString(underlyingNameId, underlyingName, false)) + return err; + } DxcHLSLTypeSymbol typeSymbol(elementsOrArrayIdDisplay, displayNameId, underlyingNameId); @@ -1706,8 +1754,10 @@ class RecursiveReflector : public DeclVisitor { {enumValue->getInitVal().getSExtValue(), childNodeId}); } - if (Refl.EnumValues.size() >= uint32_t(1 << 30)) - throw std::invalid_argument("Enum values overflow"); + if (Refl.EnumValues.size() >= uint32_t(1 << 30)) { + LastError = DXC_REFLECT_ERR("Enum values overflow"); + return; + } QualType enumType = ED->getIntegerType(); QualType desugared = enumType.getDesugaredType(ASTCtx); diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 3391e64c4f..bb4f73e4e3 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1597,10 +1597,12 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, DxcHLSLReflectionData refl; - if (DxcReflectionError err = DxcHLSLReflectionDataFromAST(refl, astHelper.compiler, *astHelper.tu, - opts.AutoBindingSpace, reflectMask, - opts.DefaultRowMajor)) - throw std::exception(("refl.Initialize failed " + std::string(err)).c_str()); + if (DxcReflectionError err = DxcHLSLReflectionDataFromAST( + refl, astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, + reflectMask, opts.DefaultRowMajor)) { + printf("refl.Initialize failed %s\n", err); //TODO: + return E_FAIL; + } //TODO: Debug @@ -1613,8 +1615,10 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, DxcHLSLReflectionData deserialized(bytes, true); - if (!(deserialized == refl)) - throw std::exception("Dump or Deserialize doesn't match"); + if (!(deserialized == refl)) { + printf("Dump or Deserialize doesn't match\n"); //TODO: + return E_FAIL; + } printf("Reflection size: %" PRIu64 "\n", bytes.size()); @@ -1627,8 +1631,10 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, DxcHLSLReflectionData deserialized2 = DxcHLSLReflectionData(bytes, false); - if (!(deserialized2 == refl)) - throw std::exception("Dump or Deserialize doesn't match"); + if (!(deserialized2 == refl)) { + printf("Dump or Deserialize doesn't match\n"); //TODO: + return E_FAIL; + } printf("Stripped reflection size: %" PRIu64 "\n", bytes.size()); From 41abd76333551d1b3e563560d10a6e4ad91b145a Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Thu, 30 Oct 2025 00:23:29 +0100 Subject: [PATCH 067/126] Added an index to DxcReflectionError for when the error is thrown in a loop and you need more information. Replaced all out_of_range and invalid_argument exceptions during deserialization with DxcReflectionError. --- include/dxc/DxcReflection/DxcReflection.h | 29 +- .../tools/dxcreflection/DxcReflection.cpp | 301 ++++++++---------- tools/clang/tools/libclang/dxcreflector.cpp | 22 +- 3 files changed, 178 insertions(+), 174 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index f7d30e3f56..a50f68467b 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -22,7 +22,26 @@ namespace hlsl { -typedef const char *DxcReflectionError; +struct DxcReflectionError { + + const char *err; + + uint32_t index; //For example which elementId made this error + bool hasIndex; + uint8_t pad[3]; + + constexpr DxcReflectionError() + : err(nullptr), index(0), hasIndex(false), pad{0, 0, 0} {} + + constexpr DxcReflectionError(const char *err) + : err(err), index(0), hasIndex(false), pad{0, 0, 0} {} + + constexpr DxcReflectionError(const char *err, uint32_t index) + : err(err), index(index), hasIndex(true), pad{0, 0, 0} {} + + operator const char *() const { return err; } +}; + static constexpr const DxcReflectionError DxcReflectionSuccess = nullptr; #ifndef NDEBUG @@ -35,9 +54,9 @@ static constexpr const DxcReflectionError DxcReflectionSuccess = nullptr; #endif #define DXC_REFLECT_STRING(x) #x #define DXC_REFLECT_STRING2(x) DXC_REFLECT_STRING(x) - #define DXC_REFLECT_ERR(x) (x " at " __FILE__ ":" DXC_REFLECT_STRING2(__LINE__) " (" DXC_FUNC_NAME ")") + #define DXC_REFLECT_ERR(x, ...) DxcReflectionError(x " at " __FILE__ ":" DXC_REFLECT_STRING2(__LINE__) " (" DXC_FUNC_NAME ")", __VA_ARGS__) #else - #define DXC_REFLECT_ERR(x) x +#define DXC_REFLECT_ERR(x, ...) DxcReflectionError(x, __VA_ARGS__) #endif class DxcHLSLNode { @@ -812,8 +831,8 @@ struct DxcHLSLReflectionData { bool GenerateNameLookupTable(); DxcHLSLReflectionData() = default; - DxcHLSLReflectionData(const std::vector &Bytes, - bool MakeNameLookupTable); + [[nodiscard]] DxcReflectionError Deserialize(const std::vector &Bytes, + bool MakeNameLookupTable); bool IsSameNonDebug(const DxcHLSLReflectionData &Other) const { return StringsNonDebug == Other.StringsNonDebug && Nodes == Other.Nodes && diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 05f1d0ba61..9a386c2878 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -700,21 +700,24 @@ void Append(std::vector &Bytes, uint64_t &Offset, } template >> -void Consume(const std::vector &Bytes, uint64_t &Offset, T &t) { +[[nodiscard]] DxcReflectionError Consume(const std::vector &Bytes, uint64_t &Offset, T &t) { static_assert(std::is_pod_v, "Consume only works on POD types"); SkipPadding(Offset); if (Offset + sizeof(T) > Bytes.size()) - throw std::out_of_range("Couldn't consume; out of bounds!"); + return DXC_REFLECT_ERR("Couldn't consume; out of bounds!"); std::memcpy(&t, &UnsafeCast(Bytes, Offset), sizeof(T)); Offset += sizeof(T); + + return DxcReflectionSuccess; } template -void Consume(const std::vector &Bytes, uint64_t &Offset, T *target, +[[nodiscard]] DxcReflectionError Consume(const std::vector &Bytes, + uint64_t &Offset, T *target, uint64_t Len) { static_assert(std::is_pod_v, "Consume only works on POD types"); @@ -722,55 +725,68 @@ void Consume(const std::vector &Bytes, uint64_t &Offset, T *target, SkipPadding(Offset); if (Offset + sizeof(T) * Len > Bytes.size()) - throw std::out_of_range("Couldn't consume; out of bounds!"); + return DXC_REFLECT_ERR("Couldn't consume; out of bounds!"); std::memcpy(target, &UnsafeCast(Bytes, Offset), sizeof(T) * Len); Offset += sizeof(T) * Len; + + return DxcReflectionSuccess; } template -void Consume(const std::vector &Bytes, uint64_t &Offset, - std::vector &Vec, uint64_t Len) { +[[nodiscard]] DxcReflectionError Consume(const std::vector &Bytes, + uint64_t &Offset, std::vector &Vec, + uint64_t Len) { Vec.resize(Len); - Consume(Bytes, Offset, Vec.data(), Len); + return Consume(Bytes, Offset, Vec.data(), Len); } template <> -void Consume(const std::vector &Bytes, uint64_t &Offset, +[[nodiscard]] DxcReflectionError +Consume(const std::vector &Bytes, uint64_t &Offset, std::vector &Vec, uint64_t Len) { Vec.resize(Len); for (uint64_t i = 0; i < Len; ++i) { if (Offset >= Bytes.size()) - throw std::out_of_range("Couldn't consume string len; out of bounds!"); + return DXC_REFLECT_ERR("Couldn't consume string len; out of bounds!"); uint16_t ourLen = uint8_t(Bytes.at(Offset++)); if (ourLen >> 7) { if (Offset >= Bytes.size()) - throw std::out_of_range("Couldn't consume string len; out of bounds!"); + return DXC_REFLECT_ERR("Couldn't consume string len; out of bounds!"); ourLen &= ~(1 << 7); ourLen |= uint16_t(Bytes.at(Offset++)) << 7; } if (Offset + ourLen > Bytes.size()) - throw std::out_of_range("Couldn't consume string len; out of bounds!"); + return DXC_REFLECT_ERR("Couldn't consume string len; out of bounds!"); Vec[i].resize(ourLen); std::memcpy(Vec[i].data(), Bytes.data() + Offset, ourLen); Offset += ourLen; } + + return DxcReflectionSuccess; } template -void Consume(const std::vector &Bytes, uint64_t &Offset, +[[nodiscard]] DxcReflectionError Consume(const std::vector &Bytes, + uint64_t &Offset, std::vector &Vec, uint64_t Len, std::vector &Vec2, uint64_t Len2, args&... arg) { - Consume(Bytes, Offset, Vec, Len); - Consume(Bytes, Offset, Vec2, Len2, arg...); + + if (DxcReflectionError err = Consume(Bytes, Offset, Vec, Len)) + return err; + + if (DxcReflectionError err = Consume(Bytes, Offset, Vec2, Len2, arg...)) + return err; + + return DxcReflectionSuccess; } static constexpr uint32_t DxcReflectionDataMagic = DXC_FOURCC('D', 'H', 'R', 'D'); @@ -925,31 +941,37 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { } } -DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes, - bool MakeNameLookupTable) { +[[nodiscard]] DxcReflectionError DxcHLSLReflectionData::Deserialize(const std::vector &Bytes, + bool MakeNameLookupTable) +{ + + *this = {}; uint64_t off = 0; DxcHLSLHeader header; - Consume(Bytes, off, header); + if (DxcReflectionError err = Consume(Bytes, off, header)) + return err; if (header.MagicNumber != DxcReflectionDataMagic) - throw std::invalid_argument("Invalid magic number"); + return DXC_REFLECT_ERR("Invalid magic number"); if (header.Version != DxcReflectionDataVersion) - throw std::invalid_argument("Unrecognized version number"); + return DXC_REFLECT_ERR("Unrecognized version number"); Features = header.Features; - bool hasSymbolInfo = Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + bool hasSymbolInfo = + Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; if (!hasSymbolInfo && (header.Sources || header.Strings)) - throw std::invalid_argument("Sources are invalid without symbols"); + return DXC_REFLECT_ERR("Sources are invalid without symbols"); uint32_t nodeSymbolCount = hasSymbolInfo ? header.Nodes : 0; uint32_t memberSymbolCount = hasSymbolInfo ? header.Members : 0; uint32_t typeSymbolCount = hasSymbolInfo ? header.Types : 0; - Consume(Bytes, off, Strings, header.Strings, StringsNonDebug, + if (DxcReflectionError err = Consume( + Bytes, off, Strings, header.Strings, StringsNonDebug, header.StringsNonDebug, Sources, header.Sources, Nodes, header.Nodes, NodeSymbols, nodeSymbolCount, Registers, header.Registers, Functions, header.Functions, Enums, header.Enums, EnumValues, header.EnumValues, @@ -957,16 +979,17 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes Arrays, header.Arrays, MemberTypeIds, header.Members, TypeList, header.TypeListCount, MemberNameIds, memberSymbolCount, Types, header.Types, TypeSymbols, typeSymbolCount, Buffers, header.Buffers, - Parameters, header.Parameters, Statements, header.Statements); + Parameters, header.Parameters, Statements, header.Statements)) + return err; - // Validation errors are throws to prevent accessing invalid data + // Validation errors to prevent accessing invalid data if (off != Bytes.size()) - throw std::invalid_argument("Reflection info had unrecognized data on the back"); + return DXC_REFLECT_ERR("Reflection info had unrecognized data on the back"); for(uint32_t i = 0; i < header.Sources; ++i) - if(Sources[i] >= header.Strings) - throw std::invalid_argument("Source path out of bounds"); + if (Sources[i] >= header.Strings) + return DXC_REFLECT_ERR("Source path out of bounds", i); std::vector validateChildren; @@ -975,21 +998,20 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLNode &node = Nodes[i]; if (hasSymbolInfo && (NodeSymbols[i].GetNameId() >= header.Strings || - (NodeSymbols[i].GetFileSourceId() != uint16_t(-1) && - NodeSymbols[i].GetFileSourceId() >= header.Sources))) - throw std::invalid_argument("Node " + std::to_string(i) + - " points to invalid name or file name"); + (NodeSymbols[i].GetFileSourceId() != uint16_t(-1) && + NodeSymbols[i].GetFileSourceId() >= header.Sources))) + return DXC_REFLECT_ERR("Node points to invalid name or file name", i); if (node.GetAnnotationStart() + node.GetAnnotationCount() > header.Annotations || node.GetNodeType() > D3D12_HLSL_NODE_TYPE_END || (i && node.GetParentId() >= i) || i + node.GetChildCount() > header.Nodes) - throw std::invalid_argument("Node " + std::to_string(i) + " is invalid"); + return DXC_REFLECT_ERR("Node is invalid", i); if (node.GetSemanticId() != uint32_t(-1) && node.GetSemanticId() >= header.StringsNonDebug) - throw std::invalid_argument("Node " + std::to_string(i) + " points to invalid semantic id"); + return DXC_REFLECT_ERR("Node points to invalid semantic id", i); uint32_t maxValue = 1; bool allowFwdDeclare = false; @@ -1018,9 +1040,8 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION) - throw std::invalid_argument( - "Node " + std::to_string(i) + - " is a parameter but parent isn't a function"); + return DXC_REFLECT_ERR( + "Node is a parameter but parent isn't a function", i); break; @@ -1047,10 +1068,9 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes break; default: - throw std::invalid_argument( - "Node " + std::to_string(i) + - " is an if/scope/do/for/while/switch but parent isn't of a similar " - "type or function"); + return DXC_REFLECT_ERR( + "Node is an if/scope/do/for/while/switch but parent isn't of a similar " + "type or function", i); } break; @@ -1079,9 +1099,8 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE: case D3D12_HLSL_NODE_TYPE_PARAMETER: if (node.GetChildCount()) - throw std::invalid_argument("Node " + std::to_string(i) + - " is a parameter, typedef, variable or " - "static variable but also has children"); + return DXC_REFLECT_ERR("Node is a parameter, typedef, variable or " + "static variable but also has children", i); case D3D12_HLSL_NODE_TYPE_IF: case D3D12_HLSL_NODE_TYPE_SCOPE: @@ -1097,17 +1116,14 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes node.GetNodeType() == D3D12_HLSL_NODE_TYPE_VARIABLE) && Nodes[node.GetParentId()].GetNodeType() == D3D12_HLSL_NODE_TYPE_INTERFACE) - throw std::invalid_argument( - "Node " + std::to_string(i) + - " is interface but has registers or variables"); + return DXC_REFLECT_ERR( + "Node is interface but has registers or variables", i); if (node.IsFwdDeclare() && !allowFwdDeclare) - throw std::invalid_argument("Node " + std::to_string(i) + - " is fwd declare but that's not permitted"); + return DXC_REFLECT_ERR("Node is fwd declare but that's not permitted", i); if (node.GetLocalId() >= maxValue) - throw std::invalid_argument("Node " + std::to_string(i) + - " has invalid localId"); + return DXC_REFLECT_ERR("Node has invalid localId", i); } for(uint32_t i = 0; i < header.Registers; ++i) { @@ -1115,29 +1131,29 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes const DxcHLSLRegister ® = Registers[i]; if(reg.GetNodeId() >= header.Nodes || - Nodes[reg.GetNodeId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER || + Nodes[reg.GetNodeId()].GetNodeType() != + D3D12_HLSL_NODE_TYPE_REGISTER || Nodes[reg.GetNodeId()].GetLocalId() != i ) - throw std::invalid_argument("Register " + std::to_string(i) + " points to an invalid nodeId"); + return DXC_REFLECT_ERR("Register points to an invalid nodeId", i); if (reg.GetType() > D3D_SIT_UAV_FEEDBACKTEXTURE || reg.GetReturnType() > D3D_RETURN_TYPE_CONTINUED || reg.GetDimension() > D3D_SRV_DIMENSION_BUFFEREX || !reg.GetBindCount() || (reg.GetArrayId() != uint32_t(-1) && reg.GetArrayId() >= header.Arrays) || (reg.GetArrayId() != uint32_t(-1) && reg.GetBindCount() <= 1)) - throw std::invalid_argument( - "Register " + std::to_string(i) + - " invalid type, returnType, bindCount, array or dimension"); + return DXC_REFLECT_ERR( + "Register invalid type, returnType, bindCount, array or dimension", i); - D3D_CBUFFER_TYPE bufferType = GetBufferType(reg.GetType()); + D3D_CBUFFER_TYPE bufferType = + DxcHLSLReflectionData::GetBufferType(reg.GetType()); if(bufferType != D3D_CT_INTERFACE_POINTERS) { if (reg.GetBufferId() >= header.Buffers || Buffers[reg.GetBufferId()].NodeId != reg.GetNodeId() || Buffers[reg.GetBufferId()].Type != bufferType) - throw std::invalid_argument("Register " + std::to_string(i) + - " invalid buffer referenced by register"); + return DXC_REFLECT_ERR("Register invalid buffer referenced by register", i); } } @@ -1149,22 +1165,19 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes Nodes[func.GetNodeId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION || Nodes[func.GetNodeId()].GetLocalId() != i) - throw std::invalid_argument("Function " + std::to_string(i) + - " points to an invalid nodeId"); + return DXC_REFLECT_ERR("Function points to an invalid nodeId", i); uint32_t paramCount = func.GetNumParameters() + func.HasReturn(); if (Nodes[func.GetNodeId()].GetChildCount() < paramCount) - throw std::invalid_argument("Function " + std::to_string(i) + - " is missing parameters and/or return"); + return DXC_REFLECT_ERR("Function is missing parameters and/or return", i); for (uint32_t j = 0; j < paramCount; ++j) if (Nodes[func.GetNodeId() + 1 + j].GetParentId() != func.GetNodeId() || Nodes[func.GetNodeId() + 1 + j].GetNodeType() != D3D12_HLSL_NODE_TYPE_PARAMETER) - throw std::invalid_argument( - "Function " + std::to_string(i) + - " is missing valid parameters and/or return"); + return DXC_REFLECT_ERR( + "Function is missing valid parameters and/or return", i); } for(uint32_t i = 0; i < header.Enums; ++i) { @@ -1174,19 +1187,16 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (enm.NodeId >= header.Nodes || Nodes[enm.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM || Nodes[enm.NodeId].GetLocalId() != i) - throw std::invalid_argument("Function " + std::to_string(i) + - " points to an invalid nodeId"); + return DXC_REFLECT_ERR("Function points to an invalid nodeId", i); if (enm.Type < D3D12_HLSL_ENUM_TYPE_START || enm.Type > D3D12_HLSL_ENUM_TYPE_END) - throw std::invalid_argument("Enum " + std::to_string(i) + - " has an invalid type"); + return DXC_REFLECT_ERR("Enum has an invalid type", i); const DxcHLSLNode &node = Nodes[enm.NodeId]; if (!node.IsFwdDeclare() && !node.GetChildCount()) - throw std::invalid_argument("Enum " + std::to_string(i) + - " has no values!"); + return DXC_REFLECT_ERR("Enum has no values!", i); for (uint32_t j = 0; j < node.GetChildCount(); ++j) { @@ -1194,8 +1204,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (child.GetChildCount() != 0 || child.GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM_VALUE) - throw std::invalid_argument("Enum " + std::to_string(i) + - " has an invalid enum value"); + return DXC_REFLECT_ERR("Enum has an invalid enum value", i); } } @@ -1208,8 +1217,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes Nodes[enumVal.NodeId].GetLocalId() != i || Nodes[Nodes[enumVal.NodeId].GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM) - throw std::invalid_argument("Enum " + std::to_string(i) + - " points to an invalid nodeId"); + return DXC_REFLECT_ERR("Enum points to an invalid nodeId", i); } for (uint32_t i = 0; i < header.Arrays; ++i) { @@ -1218,14 +1226,12 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (arr.ArrayElem() <= 1 || arr.ArrayElem() > 32 || arr.ArrayStart() + arr.ArrayElem() > header.ArraySizes) - throw std::invalid_argument("Array " + std::to_string(i) + - " points to an invalid array element"); + return DXC_REFLECT_ERR("Array points to an invalid array element", i); } for (uint32_t i = 0; i < header.Annotations; ++i) if (Annotations[i].GetStringNonDebug() >= header.StringsNonDebug) - throw std::invalid_argument("Annotation " + std::to_string(i) + - " points to an invalid string"); + return DXC_REFLECT_ERR("Annotation points to an invalid string", i); for (uint32_t i = 0; i < header.Buffers; ++i) { @@ -1235,14 +1241,12 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes Nodes[buf.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER || Nodes[buf.NodeId].GetLocalId() >= header.Registers || Registers[Nodes[buf.NodeId].GetLocalId()].GetBufferId() != i) - throw std::invalid_argument("Buffer " + std::to_string(i) + - " points to an invalid nodeId"); + return DXC_REFLECT_ERR("Buffer points to an invalid nodeId", i); const DxcHLSLNode &node = Nodes[buf.NodeId]; if (!node.GetChildCount()) - throw std::invalid_argument("Buffer " + std::to_string(i) + - " requires at least one Variable child"); + return DXC_REFLECT_ERR("Buffer requires at least one Variable child", i); for (uint32_t j = 0; j < node.GetChildCount(); ++j) { @@ -1250,26 +1254,22 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (child.GetChildCount() != 0 || child.GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) - throw std::invalid_argument("Buffer " + std::to_string(i) + - " has to have only Variable child nodes"); + return DXC_REFLECT_ERR("Buffer has to have only Variable child nodes", i); } } for (uint32_t i = 0; i < header.Members; ++i) { if (MemberTypeIds[i] >= header.Types) - throw std::invalid_argument("Member " + std::to_string(i) + - " points to an invalid type"); + return DXC_REFLECT_ERR("Member points to an invalid type", i); if (hasSymbolInfo && MemberNameIds[i] >= header.Strings) - throw std::invalid_argument("Member " + std::to_string(i) + - " points to an invalid string"); + return DXC_REFLECT_ERR("Member points to an invalid string", i); } for (uint32_t i = 0; i < header.TypeListCount; ++i) if (TypeList[i] >= header.Types) - throw std::invalid_argument("Type list index " + std::to_string(i) + - " points to an invalid type"); + return DXC_REFLECT_ERR("Type list index points to an invalid type", i); for (uint32_t i = 0; i < header.Parameters; ++i) { @@ -1278,13 +1278,11 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (param.NodeId >= header.Nodes || Nodes[param.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_PARAMETER || Nodes[param.NodeId].GetLocalId() != i || param.TypeId >= header.Types) - throw std::invalid_argument("Parameter " + std::to_string(i) + - " points to an invalid nodeId"); + return DXC_REFLECT_ERR("Parameter points to an invalid nodeId", i); if (param.Flags > 3 || param.InterpolationMode > D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE) - throw std::invalid_argument("Parameter " + std::to_string(i) + - " has invalid data"); + return DXC_REFLECT_ERR("Parameter has invalid data", i); } for (uint32_t nodeId : validateChildren) { @@ -1313,9 +1311,8 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_SWITCH: break; default: - throw std::invalid_argument( - "Node " + std::to_string(nodeId) + - " has if/then/scope with children of invalid type"); + return DXC_REFLECT_ERR( + "Node has if/then/scope with children of invalid type", nodeId); } j += childNode.GetChildCount(); @@ -1328,22 +1325,19 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (Stmt.GetNodeId() >= header.Nodes || Nodes[Stmt.GetNodeId()].GetLocalId() != i) - throw std::invalid_argument("Statement " + std::to_string(i) + - " points to an invalid nodeId"); + return DXC_REFLECT_ERR("Statement points to an invalid nodeId", i); bool condVar = Stmt.HasConditionVar(); uint32_t minParamCount = Stmt.GetNodeCount() + condVar; const DxcHLSLNode &node = Nodes[Stmt.GetNodeId()]; if (node.GetChildCount() < minParamCount) - throw std::invalid_argument("Statement " + std::to_string(i) + - " didn't have required child nodes"); + return DXC_REFLECT_ERR("Statement didn't have required child nodes", i); if (condVar && Nodes[Stmt.GetNodeId() + 1].GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) - throw std::invalid_argument( - "Statement " + std::to_string(i) + - " has condition variable but first child is not a variable"); + return DXC_REFLECT_ERR( + "Statement has condition variable but first child is not a variable", i); switch (Nodes[Stmt.GetNodeId()].GetNodeType()) { case D3D12_HLSL_NODE_TYPE_IF: @@ -1352,8 +1346,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D12_HLSL_NODE_TYPE_SWITCH: break; default: - throw std::invalid_argument("Statement " + std::to_string(i) + - " has invalid node type"); + return DXC_REFLECT_ERR("Statement has invalid node type", i); } } @@ -1363,14 +1356,13 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (hasSymbolInfo && (TypeSymbols[i].DisplayNameId >= header.Strings || TypeSymbols[i].UnderlyingNameId >= header.Strings)) - throw std::invalid_argument("Type " + std::to_string(i) + - " points to an invalid string"); + return DXC_REFLECT_ERR("Type points to an invalid string", i); - if (hasSymbolInfo && (TypeSymbols[i].DisplayArray.ElementsOrArrayId >> 31 && - (TypeSymbols[i].DisplayArray.ElementsOrArrayId << 1 >> + if (hasSymbolInfo && + (TypeSymbols[i].DisplayArray.ElementsOrArrayId >> 31 && + (TypeSymbols[i].DisplayArray.ElementsOrArrayId << 1 >> 1) >= header.Arrays)) - throw std::invalid_argument("Type " + std::to_string(i) + - " points to an invalid string"); + return DXC_REFLECT_ERR("Type points to an invalid string", i); if ((type.GetBaseClass() != uint32_t(-1) && type.GetBaseClass() >= header.Types) || @@ -1380,26 +1372,22 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes (type.GetUnderlyingArray().ElementsOrArrayId >> 31 && (type.GetUnderlyingArray().ElementsOrArrayId << 1 >> 1) >= header.Arrays)) - throw std::invalid_argument( - "Type " + std::to_string(i) + - " points to an invalid string, array, base class or member"); + return DXC_REFLECT_ERR( + "Type points to an invalid string, array, base class or member", i); switch (type.GetClass()) { case D3D_SVC_SCALAR: if (type.GetColumns() != 1) - throw std::invalid_argument("Type (scalar) " + std::to_string(i) + - " should have columns == 1"); + return DXC_REFLECT_ERR("Type (scalar) should have columns == 1", i); [[fallthrough]]; case D3D_SVC_VECTOR: if (type.GetRows() != 1) - throw std::invalid_argument("Type (scalar/vector) " + - std::to_string(i) + - " should have rows == 1"); + return DXC_REFLECT_ERR("Type (scalar/vector) should have rows == 1", i); [[fallthrough]]; @@ -1408,9 +1396,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (!type.GetRows() || !type.GetColumns() || type.GetRows() > 128 || type.GetColumns() > 128) - throw std::invalid_argument("Type (scalar/vector/matrix) " + - std::to_string(i) + - " has invalid rows or columns"); + return DXC_REFLECT_ERR("Type (scalar/vector/matrix) has invalid rows or columns", i); switch (type.GetType()) { case D3D_SVT_BOOL: @@ -1432,9 +1418,7 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes break; default: - throw std::invalid_argument("Type (scalar/matrix/vector) " + - std::to_string(i) + - " is of invalid type"); + return DXC_REFLECT_ERR("Type (scalar/matrix/vector) is of invalid type", i); } break; @@ -1442,22 +1426,17 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes case D3D_SVC_STRUCT: if (!type.GetMemberCount()) - throw std::invalid_argument("Type (struct) " + std::to_string(i) + - " is missing children"); + return DXC_REFLECT_ERR("Type (struct) is missing children", i); [[fallthrough]]; case D3D_SVC_INTERFACE_CLASS: if (type.GetType()) - throw std::invalid_argument("Type (struct) " + - std::to_string(i) + - " shouldn't have rows or columns"); + return DXC_REFLECT_ERR("Type (struct) shouldn't have rows or columns", i); if (type.GetRows() || type.GetColumns()) - throw std::invalid_argument("Type (struct) " + - std::to_string(i) + - " shouldn't have rows or columns"); + return DXC_REFLECT_ERR("Type (struct) shouldn't have rows or columns", i); break; @@ -1494,20 +1473,16 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes break; default: - throw std::invalid_argument("Type (object) " + std::to_string(i) + - " is of invalid type"); + return DXC_REFLECT_ERR("Type (object) is of invalid type", i); } if (type.GetRows() || type.GetColumns()) - throw std::invalid_argument("Type (object) " + - std::to_string(i) + - " shouldn't have rows or columns"); + return DXC_REFLECT_ERR("Type (object) shouldn't have rows or columns", i); break; default: - throw std::invalid_argument("Type " + std::to_string(i) + - " has an invalid class"); + return DXC_REFLECT_ERR("Type has an invalid class", i); } } @@ -1522,45 +1497,39 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes uint32_t fwdBack = node.GetFwdBck(); if (Nodes[fwdBack].GetNodeType() != node.GetNodeType()) - throw std::invalid_argument( - "Node " + std::to_string(i) + - " (fwd/bck declare) points to element that of incompatible type"); + return DXC_REFLECT_ERR( + "Node (fwd/bck declare) points to element that of incompatible type", i); - if (hasSymbolInfo && NodeSymbols[fwdBack].GetNameId() != NodeSymbols[i].GetNameId()) - throw std::invalid_argument( - "Node " + std::to_string(i) + - " (fwd/bck declare) have mismatching name"); + if (hasSymbolInfo && NodeSymbols[fwdBack].GetNameId() != + NodeSymbols[i].GetNameId()) + return DXC_REFLECT_ERR( + "Node (fwd/bck declare) have mismatching name", i); if (node.IsFwdDeclare()) { if (fwdBack <= i || fwdBack >= header.Nodes) - throw std::invalid_argument( - "Node " + std::to_string(i) + - " (fwd declare) points to invalid element"); + return DXC_REFLECT_ERR( + "Node (fwd declare) points to invalid element", i); if (Nodes[fwdBack].IsFwdDeclare()) - throw std::invalid_argument( - "Node " + std::to_string(i) + - " (fwd declare) points to element that is also a fwd declare"); + return DXC_REFLECT_ERR( + "Node (fwd declare) points to element that is also a fwd declare", i); if (node.GetChildCount() || node.GetAnnotationCount()) - throw std::invalid_argument( - "Node " + std::to_string(i) + - " (fwd declare) points to element with invalid child count, " - "or annotationCount"); + return DXC_REFLECT_ERR( + "Node (fwd declare) points to element with invalid child count, " + "or annotationCount", i); } else { if (fwdBack >= i) - throw std::invalid_argument( - "Node " + std::to_string(i) + - " (bck declare) points to invalid element"); + return DXC_REFLECT_ERR( + "Node (bck declare) points to invalid element", i); if (!Nodes[fwdBack].IsFwdDeclare()) - throw std::invalid_argument( - "Node " + std::to_string(i) + - " (bck declare) points to element that is not a fwd declare"); + return DXC_REFLECT_ERR( + "Node (bck declare) points to element that is not a fwd declare", i); } } } @@ -1569,6 +1538,8 @@ DxcHLSLReflectionData::DxcHLSLReflectionData(const std::vector &Bytes if (MakeNameLookupTable) GenerateNameLookupTable(); + + return DxcReflectionSuccess; } void DxcHLSLReflectionData::Printf() const { RecursePrint(*this, 0, 0, 0); } diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index bb4f73e4e3..484cb0e2dc 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1600,7 +1600,7 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, if (DxcReflectionError err = DxcHLSLReflectionDataFromAST( refl, astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, reflectMask, opts.DefaultRowMajor)) { - printf("refl.Initialize failed %s\n", err); //TODO: + printf("DxcHLSLReflectionDataFromAST failed %s\n", err.err); //TODO: return E_FAIL; } @@ -1613,7 +1613,12 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, std::vector bytes; refl.Dump(bytes); - DxcHLSLReflectionData deserialized(bytes, true); + DxcHLSLReflectionData deserialized; + + if (DxcReflectionError err = deserialized.Deserialize(bytes, true)) { + printf("Deserialize failed %s\n", err.err); // TODO: + return E_FAIL; + } if (!(deserialized == refl)) { printf("Dump or Deserialize doesn't match\n"); //TODO: @@ -1629,7 +1634,12 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, refl.Dump(bytes); - DxcHLSLReflectionData deserialized2 = DxcHLSLReflectionData(bytes, false); + DxcHLSLReflectionData deserialized2; + + if (DxcReflectionError err = deserialized2.Deserialize(bytes, true)) { + printf("Deserialize failed %s\n", err.err); // TODO: + return E_FAIL; + } if (!(deserialized2 == refl)) { printf("Dump or Deserialize doesn't match\n"); //TODO: @@ -1775,7 +1785,11 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { data->GetBufferSize()); try { - DxcHLSLReflectionData deserial(bytes, true); + DxcHLSLReflectionData deserial; + + if (DxcReflectionError err = deserial.Deserialize(bytes, true)) + return E_FAIL; + *ppReflection = new DxcHLSLReflection(std::move(deserial)); return S_OK; } catch (...) { From 1fb4095f925ed82e6894fd400d6cc772cab1c9c7 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 1 Nov 2025 23:41:23 +0100 Subject: [PATCH 068/126] Now working on a reflection -> json tool --- include/dxc/DxcReflection/DxcReflection.h | 5 +- .../tools/dxcreflection/DxcReflection.cpp | 431 +---------------- tools/clang/tools/libclang/dxcreflector.cpp | 439 +++++++++++++++++- 3 files changed, 446 insertions(+), 429 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index a50f68467b..8e7621bf8c 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -156,7 +156,8 @@ class DxcHLSLNode { // !IsFwdDeclare() && IsFwdDefined(): GetFwdBck() should point to a valid fwd // declare that points back to it. // Backwards declare should point to a NodeId < self and Forwards to > self. - // Forward declares aren't allowed to have any children. + // Forward declares aren't allowed to have any children except functions, + // which can have parameters only (inc. return). // If there's a name, they should match. // Must be same node type too. // Only allowed on functions, struct/union and enums. @@ -289,6 +290,7 @@ class DxcHLSLNodeSymbol { uint32_t GetNameId() const { return NameId; } uint16_t GetFileSourceId() const { return FileSourceId; } + bool HasFileSource() const { return FileSourceId != uint16_t(-1); } uint16_t GetSourceLineCount() const { return SourceLineCount; } uint32_t GetSourceLineStart() const { @@ -826,7 +828,6 @@ struct DxcHLSLReflectionData { static D3D_CBUFFER_TYPE GetBufferType(uint8_t Type); void Dump(std::vector &Bytes) const; - void Printf() const; void StripSymbols(); bool GenerateNameLookupTable(); diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflection/DxcReflection.cpp index 9a386c2878..16deb44da3 100644 --- a/tools/clang/tools/dxcreflection/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflection.cpp @@ -166,426 +166,6 @@ DxcHLSLReflectionData::RegisterTypeList( return DxcReflectionSuccess; } -//TODO: Debug print code - -static std::string RegisterGetArraySize(const DxcHLSLReflectionData &Refl, const DxcHLSLRegister ®) { - - if (reg.GetArrayId() != (uint32_t)-1) { - - DxcHLSLArray arr = Refl.Arrays[reg.GetArrayId()]; - std::string str; - - for (uint32_t i = 0; i < arr.ArrayElem(); ++i) - str += "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart() + i]) + "]"; - - return str; - } - - return reg.GetBindCount() > 1 ? "[" + std::to_string(reg.GetBindCount()) + "]" - : ""; -} - -static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { - - static const char *arr[] = { - "uint", "int", "uint64_t", "int64_t", "uint16_t", "int16_t", - }; - - return arr[type]; -} - -static std::string NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { - - static const char *arr[] = {"Register", - "Function", - "Enum", - "EnumValue", - "Namespace", - "Variable", - "Typedef", - "Struct", - "Union", - "StaticVariable", - "Interface", - "Parameter", - "If", - "Scope", - "Do", - "Switch", - "While", - "For", - "GroupsharedVariable"}; - - return arr[uint32_t(type)]; -} - -static std::string -PrintArray(const DxcHLSLReflectionData &Refl, const DxcHLSLArrayOrElements &Arr) { - - std::string result; - - if (Arr.IsMultiDimensionalArray()) { - - const DxcHLSLArray &arr = Refl.Arrays[Arr.GetMultiDimensionalArrayId()]; - - for (uint32_t i = 0; i < arr.ArrayElem(); ++i) - result += - "[" + std::to_string(Refl.ArraySizes[arr.ArrayStart() + i]) + "]"; - - } - - else if (Arr.IsArray()) - result += "[" + std::to_string(Arr.Get1DElements()) + "]"; - - return result; -} - -static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, - const DxcHLSLType &Type) { - - std::string type; - - if (Type.GetClass() != D3D_SVC_STRUCT && Type.GetClass() != D3D_SVC_INTERFACE_CLASS) { - - static const char *arr[] = {"void", - "bool", - "int", - "float", - "string", - NULL, - "Texture1D", - "Texture2D", - "Texture3D", - "TextureCube", - "SamplerState", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "uint", - "uint8_t", - NULL, - NULL, - NULL, - NULL, - "Buffer", - "ConstantBuffer", - NULL, - "Texture1DArray", - "Texture2DArray", - NULL, - NULL, - "Texture2DMS", - "Texture2DMSArray", - "TextureCubeArray", - NULL, - NULL, - NULL, - NULL, - "double", - "RWTexture1D", - "RWTexture1DArray", - "RWTexture2D", - "RWTexture2DArray", - "RWTexture3D", - "RWBuffer", - "ByteAddressBuffer", - "RWByteAddressBuffer", - "StructuredBuffer", - "RWStructuredBuffer", - "AppendStructuredBuffer", - "ConsumeStructuredBuffer", - "min8float", - "min10float", - "min16float", - "min12int", - "min16int", - "min16uint", - "int16_t", - "uint16_t", - "float16_t", - "int64_t", - "uint64_t"}; - - const char *ptr = arr[Type.GetType()]; - - if (ptr) - type = ptr; - } - - switch (Type.GetClass()) { - - case D3D_SVC_MATRIX_ROWS: - case D3D_SVC_VECTOR: - - type += std::to_string(Type.GetColumns()); - - if (Type.GetClass() == D3D_SVC_MATRIX_ROWS) - type += "x" + std::to_string(Type.GetRows()); - - break; - - case D3D_SVC_MATRIX_COLUMNS: - type += std::to_string(Type.GetRows()) + "x" + - std::to_string(Type.GetColumns()); - break; - } - - return type; -} - -static std::string PrintTypeInfo(const DxcHLSLReflectionData &Refl, - const DxcHLSLType &Type, - const DxcHLSLTypeSymbol &Symbol, - const std::string &PreviousTypeName) { - - std::string result = PrintArray(Refl, Type.GetUnderlyingArray()); - - // Obtain type name (returns empty if it's not a builtin type) - - if (Symbol.DisplayNameId != Symbol.UnderlyingNameId && - Symbol.UnderlyingNameId) - result += " (" + Refl.Strings[Symbol.DisplayNameId] + - PrintArray(Refl, Symbol.DisplayArray) + ")"; - - return result; -} - -static void RecursePrintType(const DxcHLSLReflectionData &Refl, uint32_t TypeId, - uint32_t Depth, const char *Prefix) { - - const DxcHLSLType &type = Refl.Types[TypeId]; - - bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - DxcHLSLTypeSymbol symbol = - hasSymbols ? Refl.TypeSymbols[TypeId] : DxcHLSLTypeSymbol(); - - std::string name = hasSymbols ? Refl.Strings[symbol.UnderlyingNameId] - : GetBuiltinTypeName(Refl, type); - - if (name.empty() && !hasSymbols) - name = "(unknown)"; - - printf("%s%s%s%s\n", std::string(Depth, '\t').c_str(), Prefix, name.c_str(), - PrintTypeInfo(Refl, type, symbol, name).c_str()); - - if (type.GetBaseClass() != uint32_t(-1)) - RecursePrintType(Refl, type.GetBaseClass(), Depth + 1, - (std::string("BaseClass ") + Prefix).c_str()); - - for (uint32_t i = 0; i < type.GetInterfaceCount(); ++i) { - - uint32_t interfaceId = type.GetInterfaceStart() + i; - - RecursePrintType(Refl, Refl.TypeList[interfaceId], Depth + 1, "Interface "); - } - - for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { - - uint32_t memberId = type.GetMemberStart() + i; - std::string prefix = - (hasSymbols ? Refl.Strings[Refl.MemberNameIds[memberId]] : "(unknown)") + ": "; - - RecursePrintType(Refl, Refl.MemberTypeIds[memberId], Depth + 1, prefix.c_str()); - } -} - -uint32_t RecursePrint(const DxcHLSLReflectionData &Refl, uint32_t NodeId, - uint32_t Depth, uint32_t IndexInParent, bool isThroughFwdDecl = false) { - - const DxcHLSLNode &node = Refl.Nodes[NodeId]; - - uint32_t typeToPrint = (uint32_t)-1; - - if (NodeId) { - - bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - if (!isThroughFwdDecl) - printf("%s%s %s%s\n", std::string(Depth - 1, '\t').c_str(), - NodeTypeToString(node.GetNodeType()).c_str(), - hasSymbols - ? Refl.Strings[Refl.NodeSymbols[NodeId].GetNameId()].c_str() - : "(unknown)", - node.IsFwdDeclare() ? " (declaration)" - : (!isThroughFwdDecl && node.IsFwdBckDefined() - ? " (definition)" - : "")); - - if (node.IsFwdBckDefined() && !node.IsFwdDeclare() && !isThroughFwdDecl) - return node.GetChildCount(); - - for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) { - - const DxcHLSLAnnotation &annotation = - Refl.Annotations[node.GetAnnotationStart() + i]; - - printf(annotation.GetIsBuiltin() ? "%s[%s]\n" : "%s[[%s]]\n", - std::string(Depth, '\t').c_str(), - Refl.StringsNonDebug[annotation.GetStringNonDebug()].c_str()); - } - - if (node.GetSemanticId() != uint32_t(-1)) - printf("%s: %s\n", std::string(Depth, '\t').c_str(), - Refl.StringsNonDebug[node.GetSemanticId()].c_str()); - - uint32_t localId = node.GetLocalId(); - - if (!node.IsFwdDeclare()) - switch (node.GetNodeType()) { - - case D3D12_HLSL_NODE_TYPE_REGISTER: { - - const DxcHLSLRegister ® = Refl.Registers[localId]; - - if (reg.GetArrayId() == (uint32_t)-1 && reg.GetBindCount() == 1) - break; - - printf("%s%s\n", std::string(Depth, '\t').c_str(), - RegisterGetArraySize(Refl, reg).c_str()); - break; - } - - case D3D12_HLSL_NODE_TYPE_UNION: - case D3D12_HLSL_NODE_TYPE_STRUCT: { // Children are Variables - - const DxcHLSLType &type = Refl.Types[localId]; - - if (type.GetBaseClass() != uint32_t(-1)) - RecursePrintType(Refl, type.GetBaseClass(), Depth, "BaseClass "); - - for (uint32_t i = 0; i < type.GetInterfaceCount(); ++i) { - - uint32_t interfaceId = type.GetInterfaceStart() + i; - - RecursePrintType(Refl, Refl.TypeList[interfaceId], Depth, - "Interface "); - } - - break; - } - - case D3D12_HLSL_NODE_TYPE_INTERFACE: - break; - - // TODO: case D3D12_HLSL_NODE_TYPE_USING: - - case D3D12_HLSL_NODE_TYPE_PARAMETER: { - - const DxcHLSLParameter ¶m = Refl.Parameters[localId]; - - if (param.InterpolationMode || param.Flags) { - - static const char *inouts[] = {NULL, "in", "out", "inout"}; - const char *inout = inouts[param.Flags]; - - static const char *interpolationModes[] = { - "", - "Constant", - "Linear", - "LinearCentroid", - "LinearNoPerspective", - "LinearNoPerspectiveCentroid", - "LinearSample", - "LinearNoPerspectiveSample"}; - - const char *interpolationMode = - interpolationModes[param.InterpolationMode]; - - printf("%s%s%s\n", std::string(Depth, '\t').c_str(), inout ? inout : "", - ((inout ? " " : "") + std::string(interpolationMode)).c_str()); - } - - typeToPrint = param.TypeId; - break; - } - - case D3D12_HLSL_NODE_TYPE_WHILE: - case D3D12_HLSL_NODE_TYPE_FOR: - case D3D12_HLSL_NODE_TYPE_SWITCH: - case D3D12_HLSL_NODE_TYPE_IF: { - - const DxcHLSLStatement &Stmt = Refl.Statements[localId]; - const DxcHLSLNode &Node = Refl.Nodes[Stmt.GetNodeId()]; - - uint32_t bodyNodes = - Node.GetChildCount() - Stmt.GetNodeCount() - Stmt.HasConditionVar(); - - bool isIf = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF; - bool isFor = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_FOR; - - if (bodyNodes || Stmt.GetNodeCount() || Stmt.HasConditionVar() || - Stmt.HasElse()) { - - if (isIf || isFor) - printf("%s%snodes: %u, %snodes: %u%s%s\n", - std::string(Depth, '\t').c_str(), isIf ? "if " : "init ", - Stmt.GetNodeCount(), isIf ? "else " : "body ", bodyNodes, - Stmt.HasConditionVar() ? " (has cond var)" : "", - Stmt.HasElse() ? " (has else)" : ""); - - else - printf("%sbody nodes: %u%s\n", std::string(Depth, '\t').c_str(), - bodyNodes, Stmt.HasConditionVar() ? " (has cond var)" : ""); - } - - break; - } - - case D3D12_HLSL_NODE_TYPE_TYPEDEF: - case D3D12_HLSL_NODE_TYPE_VARIABLE: - case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: - case D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE: - typeToPrint = localId; - break; - - case D3D12_HLSL_NODE_TYPE_FUNCTION: { - const DxcHLSLFunction &func = Refl.Functions[localId]; - printf("%sreturn: %s, hasDefinition: %s, numParams: %u\n", - std::string(Depth, '\t').c_str(), - func.HasReturn() ? "true" : "false", - func.HasDefinition() ? "true" : "false", - func.GetNumParameters()); - - break; - } - - case D3D12_HLSL_NODE_TYPE_ENUM: - printf("%s: %s\n", std::string(Depth, '\t').c_str(), - EnumTypeToString(Refl.Enums[localId].Type).c_str()); - break; - - case D3D12_HLSL_NODE_TYPE_ENUM_VALUE: { - printf("%s#%u = %" PRIi64 "\n", std::string(Depth, '\t').c_str(), - IndexInParent, Refl.EnumValues[localId].Value); - break; - } - - case D3D12_HLSL_NODE_TYPE_NAMESPACE: - case D3D12_HLSL_NODE_TYPE_SCOPE: - case D3D12_HLSL_NODE_TYPE_DO: - default: - break; - } - } - - if (typeToPrint != (uint32_t)-1) - RecursePrintType(Refl, typeToPrint, Depth, ""); - - for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) - i += RecursePrint(Refl, NodeId + 1 + i, Depth + 1, j); - - if (node.IsFwdDeclare() && node.IsFwdBckDefined()) - RecursePrint(Refl, node.GetFwdBck(), Depth, IndexInParent, true); - - return node.GetChildCount(); -} - struct DxcHLSLHeader { uint32_t MagicNumber; @@ -1515,7 +1095,14 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { return DXC_REFLECT_ERR( "Node (fwd declare) points to element that is also a fwd declare", i); - if (node.GetChildCount() || node.GetAnnotationCount()) + uint32_t paramCount = 0; + + if (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_FUNCTION) { + const DxcHLSLFunction &func = Functions[node.GetLocalId()]; + paramCount = func.GetNumParameters() + func.HasReturn(); + } + + if ((node.GetChildCount() != paramCount) || node.GetAnnotationCount()) return DXC_REFLECT_ERR( "Node (fwd declare) points to element with invalid child count, " "or annotationCount", i); @@ -1542,6 +1129,4 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { return DxcReflectionSuccess; } -void DxcHLSLReflectionData::Printf() const { RecursePrint(*this, 0, 0, 0); } - } // namespace hlsl diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 484cb0e2dc..128fb2cc72 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -45,6 +45,8 @@ #include "dxc/DxcReflection/DxcReflection.h" +#include + using namespace llvm; using namespace clang; using namespace hlsl; @@ -1547,6 +1549,436 @@ HRESULT GenerateAST(DxcLangExtensionsHelper *pExtHelper, LPCSTR pFileName, return S_OK; } +//TODO: Print escape character + +struct JsonWriter { + + std::stringstream ss; + uint16_t indent = 0; + uint16_t countCommaStack = 0; + uint32_t needCommaStack = 0; + + void Indent() { ss << std::string(indent, '\t'); } + void NewLine() { ss << "\n"; } + + void StartCommaStack() { + ++countCommaStack; + assert(countCommaStack < 32 && "countCommaStack out of bounds"); + needCommaStack &= ~(1u << countCommaStack); + } + + void SetComma() { needCommaStack |= 1u << countCommaStack; } + + void EndCommaStack() { + --countCommaStack; + SetComma(); + } + + bool NeedsComma() { return (needCommaStack >> countCommaStack) & 1; } + + void BeginObj() { + + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + + ss << "{\n"; + ++indent; + StartCommaStack(); + Indent(); + } + + void EndObj() { + ss << "\n"; + --indent; + Indent(); + ss << "}"; + EndCommaStack(); + } + + void BeginArray(const char *Name) { + + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + + if (Name) { + StartCommaStack(); + Key(Name); + --countCommaStack; + } + + ss << "[\n"; + ++indent; + StartCommaStack(); + Indent(); + } + + void EndArray() { + ss << "\n"; + --indent; + Indent(); + ss << "]"; + EndCommaStack(); + } + + void Key(const char *Key) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << "\"" << Key << "\": "; + } + + void Value(std::string S) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << "\"" << Escape(S) << "\""; + SetComma(); + } + + void Value(const char *S) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << "\"" << S << "\""; + SetComma(); + } + + void ValueNull() { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << "null"; + SetComma(); + } + + void Value(uint64_t V) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << V; + SetComma(); + } + + void Value(int64_t V) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << V; + SetComma(); + } + + void Value(bool V) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << (V ? "true" : "false"); + SetComma(); + } + + static std::string Escape(const std::string &In) { + std::string out; + out.reserve(In.size()); + for (char c : In) { + switch (c) { + case '\\': + out += "\\\\"; + break; + case '"': + out += "\\\""; + break; + case '\n': + out += "\\n"; + break; + case '\r': + out += "\\r"; + break; + case '\t': + out += "\\t"; + break; + default: + out += c; + break; + } + } + return out; + } + + std::string str() const { return ss.str(); } + + struct ObjectScope { + + JsonWriter &W; + bool NeedsEndCommaStack; + + ObjectScope(JsonWriter &W, const char *Name = nullptr) + : W(W), NeedsEndCommaStack(Name) { + + if (Name) { + W.Key(Name); + W.StartCommaStack(); + } + + W.BeginObj(); + } + + ~ObjectScope() { + W.EndObj(); + + if (NeedsEndCommaStack) + W.EndCommaStack(); + } + }; + + struct ArrayScope { + JsonWriter &W; + ArrayScope(JsonWriter &W, const char *Name = nullptr) : W(W) { + W.BeginArray(Name); + } + ~ArrayScope() { W.EndArray(); } + }; + + void Object(const char *Name, const std::function &Body) { + ObjectScope _(*this, Name); + Body(); + } + + void Array(const char *Name, const std::function &Body) { + ArrayScope _( *this, Name ); Body(); + } + + void StringField(const char *K, const std::string &V) { + Key(K); + StartCommaStack(); + Value(V); + EndCommaStack(); + } + + void UIntField(const char *K, uint64_t V) { + Key(K); + StartCommaStack(); + Value(V); + EndCommaStack(); + } + + void IntField(const char *K, int64_t V) { + Key(K); + StartCommaStack(); + Value(V); + EndCommaStack(); + } + + void BoolField(const char *K, bool V) { + Key(K); + StartCommaStack(); + Value(V); + EndCommaStack(); + } + + void NullField(const char *K) { + Key(K); + StartCommaStack(); + ValueNull(); + EndCommaStack(); + } + +}; + +void PrintFeatures(D3D12_HLSL_REFLECTION_FEATURE Features, JsonWriter &Json) { + Json.Array("Features", [Features, &Json] { + if (Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS) + Json.Value("Basics"); + if (Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS) + Json.Value("Functions"); + if (Features & D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES) + Json.Value("Namespaces"); + if (Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES) + Json.Value("UserTypes"); + if (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES) + Json.Value("Scopes"); + if (Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + Json.Value("Symbols"); + }); +} + +static const char *NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { + + static const char *arr[] = {"Register", + "Function", + "Enum", + "EnumValue", + "Namespace", + "Variable", + "Typedef", + "Struct", + "Union", + "StaticVariable", + "Interface", + "Parameter", + "If", + "Scope", + "Do", + "Switch", + "While", + "For", + "GroupsharedVariable"}; + + return arr[uint32_t(type)]; +} + +static void PrintNode(JsonWriter &Json, DxcHLSLReflectionData &Reflection, + uint32_t NodeId, bool IsVerbose) { + + DxcHLSLNode &node = Reflection.Nodes[NodeId]; + + JsonWriter::ObjectScope nodeRoot(Json); + Json.UIntField("NodeId", NodeId); + Json.StringField("NodeType", NodeTypeToString(node.GetNodeType())); + + if (IsVerbose) + Json.UIntField("NodeTypeId", node.GetNodeType()); + + Json.UIntField("LocalId", node.GetLocalId()); + Json.UIntField("ParentId", node.GetParentId()); + + if (IsVerbose || node.GetChildCount()) { + Json.UIntField("ChildCount", node.GetChildCount()); + Json.UIntField("ChildStart", NodeId + 1); + } + + if (node.GetSemanticId() != uint32_t(-1) || IsVerbose) + Json.StringField("Semantic", + node.GetSemanticId() != uint32_t(-1) + ? Reflection.StringsNonDebug[node.GetSemanticId()] + : ""); + + if (IsVerbose) { + Json.UIntField("SemanticId", node.GetSemanticId()); + Json.UIntField("AnnotationStart", node.GetAnnotationStart()); + Json.UIntField("AnnotationCount", node.GetAnnotationCount()); + } + + if (node.GetAnnotationCount() || IsVerbose) + Json.Array("Annotations", [&Reflection, &Json, node] { + for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) + Json.Value(Reflection.StringsNonDebug[i]); + }); + + if ((node.IsFwdBckDefined() || node.IsFwdDeclare()) || IsVerbose) { + Json.BoolField("IsFwdDeclare", node.IsFwdDeclare()); + Json.BoolField("IsFwdBackDefined", node.IsFwdBckDefined()); + + if (node.IsFwdBckDefined() || IsVerbose) + Json.UIntField("FwdBack", node.GetFwdBck()); + } + + if (Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { + + Json.Object("Symbol", [&Reflection, &Json, NodeId, IsVerbose] { + DxcHLSLNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; + Json.StringField("Name", Reflection.Strings[sym.GetNameId()]); + + if (IsVerbose) + Json.UIntField("NameId", sym.GetNameId()); + + if (sym.HasFileSource()) { + + Json.StringField( + "Source", + Reflection.Strings[Reflection.Sources[sym.GetFileSourceId()]]); + + if (IsVerbose) + Json.UIntField("SourceId", sym.GetFileSourceId()); + + Json.UIntField("LineId", sym.GetSourceLineStart()); + Json.UIntField("LineCount", sym.GetSourceLineCount()); + + Json.UIntField("ColumnStart", sym.GetSourceColumnStart()); + Json.UIntField("ColumnEnd", sym.GetSourceColumnEnd()); + + } else if (IsVerbose) { + + Json.StringField("Source", ""); + Json.IntField("SourceId", -1); + + Json.IntField("LineId", -1); + Json.UIntField("LineCount", 0); + + Json.IntField("ColumnStart", -1); + Json.UIntField("ColumnEnd", 0); + } + }); + + } else if (IsVerbose) + Json.NullField("Symbol"); +} + +//IsHumanFriendly = false: Raw view of the real file data +//IsHumanFriendly = true: Clean view that's relatively close to the real tree +static std::string ToJson(DxcHLSLReflectionData &Reflection, + bool IsHumanFriendly, bool IsVerbose) { + + JsonWriter json; + + { + JsonWriter::ObjectScope root(json); + + // Features + + PrintFeatures(Reflection.Features, json); + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + // Print raw contents + + if (!IsHumanFriendly) { + + json.Array("Strings", [&Reflection, &json] { + for (const std::string &s : Reflection.Strings) + json.Value(s); + }); + + json.Array("StringsNonDebug", [&Reflection, &json] { + for (const std::string &s : Reflection.StringsNonDebug) + json.Value(s); + }); + + json.Array("Sources", [&Reflection, &json] { + for (uint32_t id : Reflection.Sources) + json.Value(Reflection.Strings[id]); + }); + + if (IsVerbose) + json.Array("SourcesAsId", [&Reflection, &json] { + for (uint32_t id : Reflection.Sources) + json.Value(uint64_t(id)); + }); + + json.Array("Nodes", [&Reflection, &json, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Reflection.Nodes.size()); ++i) + PrintNode(json, Reflection, i, IsVerbose); + }); + } + + else { + // TODO: Print pretty tree for user + } + } + + return json.str(); +} + HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, ASTUnit::RemappedFile *pRemap, hlsl::options::DxcOpts &opts, DxcDefine *pDefines, @@ -1604,9 +2036,7 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, return E_FAIL; } - //TODO: Debug - - refl.Printf(); + printf("%s\n", ToJson(refl, false, false).c_str()); // Test serialization @@ -1630,7 +2060,8 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, // Test stripping symbols refl.StripSymbols(); - refl.Printf(); + + printf("%s\n", ToJson(refl, false, false).c_str()); refl.Dump(bytes); From f59f36c6f9ddcec6ff9026cf4ccf65382a1f587d Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 2 Nov 2025 18:14:01 +0100 Subject: [PATCH 069/126] Added stringify for Registers --- tools/clang/tools/libclang/dxcreflector.cpp | 118 +++++++++++++++++++- 1 file changed, 116 insertions(+), 2 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 128fb2cc72..3d5d805067 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1811,7 +1811,7 @@ void PrintFeatures(D3D12_HLSL_REFLECTION_FEATURE Features, JsonWriter &Json) { }); } -static const char *NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { +static const char *NodeTypeToString(D3D12_HLSL_NODE_TYPE Type) { static const char *arr[] = {"Register", "Function", @@ -1833,7 +1833,45 @@ static const char *NodeTypeToString(D3D12_HLSL_NODE_TYPE type) { "For", "GroupsharedVariable"}; - return arr[uint32_t(type)]; + return arr[uint32_t(Type)]; +} + +static const char *RegisterTypeToString(D3D_SHADER_INPUT_TYPE Type) { + + static const char *arr[] = {"cbuffer", + "tbuffer", + "Texture", + "SamplerState", + "RWTexture", + "StructuredBuffer", + "RWStructuredBuffer", + "ByteAddressBuffer", + "RWByteAddressBuffer", + "AppendStructuredBuffer", + "ConsumeStructuredBuffer", + "(Append/Consume)StructuredBuffer", + "RaytracingAccelerationStructure", + "FeedbackTexture"}; + + return arr[uint32_t(Type)]; +} + +static const char *DimensionTypeToString(D3D_SRV_DIMENSION Type) { + + static const char *arr[] = { + "Unknown", "Buffer", "Texture1D", "Texture1DArray", + "Texture2D", "Texture2DArray", "Texture2DMS", "Texture2DMSArray", + "Texture3D", "TextureCube", "TextureCubeArray", "BufferEx"}; + + return arr[uint32_t(Type)]; +} + +static const char *ReturnTypeToString(D3D_RESOURCE_RETURN_TYPE Type) { + + static const char *arr[] = {"unknown", "unorm", "snorm", "sint", "uint", + "float", "mixed", "double", "continued"}; + + return arr[uint32_t(Type)]; } static void PrintNode(JsonWriter &Json, DxcHLSLReflectionData &Reflection, @@ -1923,6 +1961,77 @@ static void PrintNode(JsonWriter &Json, DxcHLSLReflectionData &Reflection, Json.NullField("Symbol"); } +static void PrintRegister(JsonWriter &Json, DxcHLSLReflectionData &Reflection, + uint32_t RegisterId, bool IsVerbose) { + + DxcHLSLRegister ® = Reflection.Registers[RegisterId]; + + JsonWriter::ObjectScope nodeRoot(Json); + Json.UIntField("RegisterId", RegisterId); + Json.UIntField("NodeId", reg.GetNodeId()); + Json.StringField("RegisterType", RegisterTypeToString(reg.GetType())); + + if (reg.GetDimension() != D3D_SRV_DIMENSION_UNKNOWN || IsVerbose) + Json.StringField("Dimension", DimensionTypeToString(reg.GetDimension())); + + if (reg.GetReturnType() || IsVerbose) + Json.StringField("ReturnType", ReturnTypeToString(reg.GetReturnType())); + + if (reg.GetBindCount() > 1 || IsVerbose) + Json.UIntField("BindCount", reg.GetBindCount()); + + if (reg.GetArrayId() != uint32_t(-1) || IsVerbose) { + + if (IsVerbose) + Json.UIntField("ArrayId", reg.GetArrayId()); + + Json.Array("ArraySize", [&Reflection, ®, &Json]() { + const DxcHLSLArray &arr = Reflection.Arrays[reg.GetArrayId()]; + + for (uint32_t i = 0; i < uint32_t(arr.ArrayElem()); ++i) + Json.Value(uint64_t(Reflection.ArraySizes[arr.ArrayStart() + i])); + }); + } + + bool isBuffer = true; + + switch (reg.GetType()) { + case D3D_SIT_TEXTURE: + case D3D_SIT_SAMPLER: + case D3D_SIT_UAV_RWTYPED: + case D3D_SIT_RTACCELERATIONSTRUCTURE: + case D3D_SIT_UAV_FEEDBACKTEXTURE: + isBuffer = false; + break; + } + + if (isBuffer || IsVerbose) + Json.UIntField("BufferId", reg.GetBufferId()); + + if (reg.GetFlags() || IsVerbose) { + + Json.Array("Flags", [®, &Json]() { + + uint32_t flag = reg.GetFlags(); + + if (flag & D3D_SIF_USERPACKED) + Json.Value("UserPacked"); + + if (flag & D3D_SIF_COMPARISON_SAMPLER) + Json.Value("ComparisonSampler"); + + if (flag & D3D_SIF_TEXTURE_COMPONENT_0) + Json.Value("TextureComponent0"); + + if (flag & D3D_SIF_TEXTURE_COMPONENT_1) + Json.Value("TextureComponent1"); + + if (flag & D3D_SIF_UNUSED) + Json.Value("Unused"); + }); + } +} + //IsHumanFriendly = false: Raw view of the real file data //IsHumanFriendly = true: Clean view that's relatively close to the real tree static std::string ToJson(DxcHLSLReflectionData &Reflection, @@ -1969,6 +2078,11 @@ static std::string ToJson(DxcHLSLReflectionData &Reflection, for (uint32_t i = 0; i < uint32_t(Reflection.Nodes.size()); ++i) PrintNode(json, Reflection, i, IsVerbose); }); + + json.Array("Registers", [&Reflection, &json, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Reflection.Registers.size()); ++i) + PrintRegister(json, Reflection, i, IsVerbose); + }); } else { From fc7f310074f7a9be4691f1df71413adaffbd007d Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 2 Nov 2025 21:24:01 +0100 Subject: [PATCH 070/126] Added function to json with all parameters --- tools/clang/tools/libclang/dxcreflector.cpp | 284 +++++++++++++++++++- 1 file changed, 283 insertions(+), 1 deletion(-) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 3d5d805067..649f6d6b4f 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1629,7 +1629,7 @@ struct JsonWriter { ss << ",\n"; Indent(); } - ss << "\"" << Key << "\": "; + ss << "\"" << Escape(Key) << "\": "; } void Value(std::string S) { @@ -1969,6 +1969,16 @@ static void PrintRegister(JsonWriter &Json, DxcHLSLReflectionData &Reflection, JsonWriter::ObjectScope nodeRoot(Json); Json.UIntField("RegisterId", RegisterId); Json.UIntField("NodeId", reg.GetNodeId()); + + if (Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + Json.StringField( + "Name", + Reflection + .Strings[Reflection.NodeSymbols[reg.GetNodeId()].GetNameId()]); + + else if (IsVerbose) + Json.StringField("Name", ""); + Json.StringField("RegisterType", RegisterTypeToString(reg.GetType())); if (reg.GetDimension() != D3D_SRV_DIMENSION_UNKNOWN || IsVerbose) @@ -2032,6 +2042,273 @@ static void PrintRegister(JsonWriter &Json, DxcHLSLReflectionData &Reflection, } } +static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, + const DxcHLSLType &Type) { + + std::string type = ""; + + if (Type.GetClass() != D3D_SVC_STRUCT && Type.GetClass() != D3D_SVC_INTERFACE_CLASS) { + + static const char *arr[] = {"void", + "bool", + "int", + "float", + "string", + NULL, + "Texture1D", + "Texture2D", + "Texture3D", + "TextureCube", + "SamplerState", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "uint", + "uint8_t", + NULL, + NULL, + NULL, + NULL, + "Buffer", + "ConstantBuffer", + NULL, + "Texture1DArray", + "Texture2DArray", + NULL, + NULL, + "Texture2DMS", + "Texture2DMSArray", + "TextureCubeArray", + NULL, + NULL, + NULL, + NULL, + "double", + "RWTexture1D", + "RWTexture1DArray", + "RWTexture2D", + "RWTexture2DArray", + "RWTexture3D", + "RWBuffer", + "ByteAddressBuffer", + "RWByteAddressBuffer", + "StructuredBuffer", + "RWStructuredBuffer", + "AppendStructuredBuffer", + "ConsumeStructuredBuffer", + "min8float", + "min10float", + "min16float", + "min12int", + "min16int", + "min16uint", + "int16_t", + "uint16_t", + "float16_t", + "int64_t", + "uint64_t"}; + + const char *ptr = arr[Type.GetType()]; + + if (ptr) + type = ptr; + } + + switch (Type.GetClass()) { + + case D3D_SVC_MATRIX_ROWS: + case D3D_SVC_VECTOR: + + type += std::to_string(Type.GetColumns()); + + if (Type.GetClass() == D3D_SVC_MATRIX_ROWS) + type += "x" + std::to_string(Type.GetRows()); + + break; + + case D3D_SVC_MATRIX_COLUMNS: + type += std::to_string(Type.GetRows()) + "x" + + std::to_string(Type.GetColumns()); + break; + } + + return type; +} + +static void FillArraySizes(DxcHLSLReflectionData &Reflection, + DxcHLSLArrayOrElements Elements, + std::vector &Array) { + + if (!Elements.IsArray()) + return; + + if (Elements.Is1DArray()) { + Array.push_back(Elements.Get1DElements()); + return; + } + + const DxcHLSLArray &arr = + Reflection.Arrays[Elements.GetMultiDimensionalArrayId()]; + + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) + Array.push_back(Reflection.ArraySizes[arr.ArrayStart() + i]); +} + +static void PrintTypeName(DxcHLSLReflectionData &Reflection, uint32_t TypeId, + bool HasSymbols, bool IsVerbose, JsonWriter &Json) { + + Json.UIntField("TypeId", TypeId); + + std::string name; + std::vector arraySizes; + + std::string underlyingName; + std::vector underlyingArraySizes; + + const DxcHLSLType &type = Reflection.Types[TypeId]; + + if (!HasSymbols) { + name = GetBuiltinTypeName(Reflection, type); + FillArraySizes(Reflection, type.GetUnderlyingArray(), arraySizes); + } + + else { + const DxcHLSLTypeSymbol &symbol = Reflection.TypeSymbols[TypeId]; + name = Reflection.Strings[symbol.DisplayNameId]; + FillArraySizes(Reflection, symbol.DisplayArray, arraySizes); + underlyingName = Reflection.Strings[symbol.UnderlyingNameId]; + FillArraySizes(Reflection, type.GetUnderlyingArray(), underlyingArraySizes); + } + + if (name.size() || IsVerbose) + Json.StringField("Name", name); + + if (arraySizes.size() || IsVerbose) + Json.Array("ArraySize", [&arraySizes, &Json]() { + for (uint32_t i : arraySizes) + Json.Value(uint64_t(i)); + }); + + if (underlyingName.size() || IsVerbose) + Json.StringField("UnderlyingName", underlyingName); + + if (underlyingArraySizes.size() || IsVerbose) + Json.Array("UnderlyingArraySize", [&underlyingArraySizes, &Json]() { + for (uint32_t i : underlyingArraySizes) + Json.Value(uint64_t(i)); + }); +} + +static void PrintParameter(DxcHLSLReflectionData &Reflection, uint32_t TypeId, + bool HasSymbols, bool IsVerbose, JsonWriter &Json, + uint32_t SemanticId, uint8_t InterpolationMode, + uint8_t Flags) { + + PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, Json); + + if (SemanticId != uint32_t(-1) || IsVerbose) + Json.StringField("Semantic", Reflection.StringsNonDebug[SemanticId]); + + if (IsVerbose) + Json.UIntField("SemanticId", SemanticId); + + if ((Flags & (D3D_PF_IN | D3D_PF_OUT)) == (D3D_PF_IN | D3D_PF_OUT)) + Json.StringField("Access", "inout"); + + else if (Flags & D3D_PF_IN) + Json.StringField("Access", "in"); + + else if (Flags & D3D_PF_OUT) + Json.StringField("Access", "out"); + + else if (IsVerbose) + Json.StringField("Access", "in"); + + static const char *interpolationModes[] = {"Undefined", + "Constant", + "Linear", + "LinearCentroid", + "LinearNoperspective", + "LinearNoperspectiveCentroid", + "LinearSample", + "LinearNoperspectiveSample"}; + + if (InterpolationMode || IsVerbose) + Json.StringField("Interpolation", interpolationModes[InterpolationMode]); +} + +static void PrintFunction(JsonWriter &Json, DxcHLSLReflectionData &Reflection, + uint32_t FunctionId, bool IsVerbose) { + + DxcHLSLFunction &func = Reflection.Functions[FunctionId]; + + JsonWriter::ObjectScope nodeRoot(Json); + + Json.UIntField("FunctionId", FunctionId); + Json.UIntField("NodeId", func.GetNodeId()); + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (hasSymbols) + Json.StringField( + "Name", + Reflection + .Strings[Reflection.NodeSymbols[func.GetNodeId()].GetNameId()]); + + else if (IsVerbose) + Json.StringField("Name", ""); + + Json.BoolField("HasDefinition", func.HasDefinition()); + + if (IsVerbose) { + Json.UIntField("NumParameters", func.GetNumParameters()); + Json.BoolField("HasReturn", func.HasReturn()); + } + + Json.Object("Params", [&Reflection, &func, &Json, hasSymbols, IsVerbose]() { + for (uint32_t i = 0; i < uint32_t(func.GetNumParameters()); ++i) { + + uint32_t nodeId = func.GetNodeId() + 1 + i; + const DxcHLSLNode &node = Reflection.Nodes[nodeId]; + uint32_t localId = node.GetLocalId(); + + const DxcHLSLParameter ¶m = Reflection.Parameters[localId]; + std::string paramName = + hasSymbols + ? Reflection.Strings[Reflection.NodeSymbols[nodeId].GetNameId()] + : std::to_string(i); + + Json.Object(paramName.c_str(), [&Reflection, &func, &Json, hasSymbols, + IsVerbose, ¶m, &node]() { + PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, Json, + node.GetSemanticId(), param.InterpolationMode, param.Flags); + }); + } + }); + + if (!func.HasReturn()) + Json.StringField("ReturnType", "void"); + + else { + + const DxcHLSLNode &node = + Reflection.Nodes[func.GetNodeId() + 1 + func.GetNumParameters()]; + const DxcHLSLParameter ¶m = Reflection.Parameters[node.GetLocalId()]; + + Json.Object("ReturnType", [&Reflection, &func, &Json, hasSymbols, IsVerbose, + ¶m, &node]() { + PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, Json, + node.GetSemanticId(), param.InterpolationMode, param.Flags); + }); + } +} + //IsHumanFriendly = false: Raw view of the real file data //IsHumanFriendly = true: Clean view that's relatively close to the real tree static std::string ToJson(DxcHLSLReflectionData &Reflection, @@ -2083,6 +2360,11 @@ static std::string ToJson(DxcHLSLReflectionData &Reflection, for (uint32_t i = 0; i < uint32_t(Reflection.Registers.size()); ++i) PrintRegister(json, Reflection, i, IsVerbose); }); + + json.Array("Functions", [&Reflection, &json, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Reflection.Functions.size()); ++i) + PrintFunction(json, Reflection, i, IsVerbose); + }); } else { From 7050c83bd7ea0d9281f5680b610cf679e8528759 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 2 Nov 2025 22:01:54 +0100 Subject: [PATCH 071/126] Almost finished exposing the raw reflection data as json --- tools/clang/tools/libclang/dxcreflector.cpp | 418 ++++++++++++-------- 1 file changed, 255 insertions(+), 163 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 649f6d6b4f..33499cb97b 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1874,22 +1874,150 @@ static const char *ReturnTypeToString(D3D_RESOURCE_RETURN_TYPE Type) { return arr[uint32_t(Type)]; } +static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, + const DxcHLSLType &Type) { + + std::string type = ""; + + if (Type.GetClass() != D3D_SVC_STRUCT && Type.GetClass() != D3D_SVC_INTERFACE_CLASS) { + + static const char *arr[] = {"void", + "bool", + "int", + "float", + "string", + NULL, + "Texture1D", + "Texture2D", + "Texture3D", + "TextureCube", + "SamplerState", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "uint", + "uint8_t", + NULL, + NULL, + NULL, + NULL, + "Buffer", + "ConstantBuffer", + NULL, + "Texture1DArray", + "Texture2DArray", + NULL, + NULL, + "Texture2DMS", + "Texture2DMSArray", + "TextureCubeArray", + NULL, + NULL, + NULL, + NULL, + "double", + "RWTexture1D", + "RWTexture1DArray", + "RWTexture2D", + "RWTexture2DArray", + "RWTexture3D", + "RWBuffer", + "ByteAddressBuffer", + "RWByteAddressBuffer", + "StructuredBuffer", + "RWStructuredBuffer", + "AppendStructuredBuffer", + "ConsumeStructuredBuffer", + "min8float", + "min10float", + "min16float", + "min12int", + "min16int", + "min16uint", + "int16_t", + "uint16_t", + "float16_t", + "int64_t", + "uint64_t"}; + + const char *ptr = arr[Type.GetType()]; + + if (ptr) + type = ptr; + } + + switch (Type.GetClass()) { + + case D3D_SVC_MATRIX_ROWS: + case D3D_SVC_VECTOR: + + type += std::to_string(Type.GetColumns()); + + if (Type.GetClass() == D3D_SVC_MATRIX_ROWS) + type += "x" + std::to_string(Type.GetRows()); + + break; + + case D3D_SVC_MATRIX_COLUMNS: + type += std::to_string(Type.GetRows()) + "x" + + std::to_string(Type.GetColumns()); + break; + } + + return type; +} + +static void FillArraySizes(DxcHLSLReflectionData &Reflection, + DxcHLSLArrayOrElements Elements, + std::vector &Array) { + + if (!Elements.IsArray()) + return; + + if (Elements.Is1DArray()) { + Array.push_back(Elements.Get1DElements()); + return; + } + + const DxcHLSLArray &arr = + Reflection.Arrays[Elements.GetMultiDimensionalArrayId()]; + + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) + Array.push_back(Reflection.ArraySizes[arr.ArrayStart() + i]); +} + +//Verbose and all members are slightly different; +//Verbose will still print fields even if they aren't relevant, +// while all members will not silence important info but that might not matter for human readability static void PrintNode(JsonWriter &Json, DxcHLSLReflectionData &Reflection, - uint32_t NodeId, bool IsVerbose) { + uint32_t NodeId, bool IsVerbose, bool AllRelevantMembers) { DxcHLSLNode &node = Reflection.Nodes[NodeId]; JsonWriter::ObjectScope nodeRoot(Json); - Json.UIntField("NodeId", NodeId); + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (AllRelevantMembers || IsVerbose || !hasSymbols) + Json.UIntField("NodeId", NodeId); + Json.StringField("NodeType", NodeTypeToString(node.GetNodeType())); - if (IsVerbose) + if (IsVerbose || AllRelevantMembers) { Json.UIntField("NodeTypeId", node.GetNodeType()); + Json.UIntField("LocalId", node.GetLocalId()); + Json.IntField("ParentId", node.GetParentId() == uint16_t(-1) + ? -1 + : int64_t(node.GetParentId())); + } - Json.UIntField("LocalId", node.GetLocalId()); - Json.UIntField("ParentId", node.GetParentId()); - - if (IsVerbose || node.GetChildCount()) { + if (IsVerbose || (node.GetChildCount() && AllRelevantMembers)) { Json.UIntField("ChildCount", node.GetChildCount()); Json.UIntField("ChildStart", NodeId + 1); } @@ -1900,33 +2028,51 @@ static void PrintNode(JsonWriter &Json, DxcHLSLReflectionData &Reflection, ? Reflection.StringsNonDebug[node.GetSemanticId()] : ""); - if (IsVerbose) { - Json.UIntField("SemanticId", node.GetSemanticId()); + if (IsVerbose || (AllRelevantMembers && node.GetSemanticId() != uint32_t(-1))) + Json.IntField("SemanticId", node.GetSemanticId() == uint32_t(-1) ? -1 : int64_t(node.GetSemanticId())); + + if (IsVerbose || (AllRelevantMembers && node.GetAnnotationCount())) { Json.UIntField("AnnotationStart", node.GetAnnotationStart()); Json.UIntField("AnnotationCount", node.GetAnnotationCount()); } if (node.GetAnnotationCount() || IsVerbose) Json.Array("Annotations", [&Reflection, &Json, node] { - for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) - Json.Value(Reflection.StringsNonDebug[i]); + for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) { + + const DxcHLSLAnnotation &annot = + Reflection.Annotations[node.GetAnnotationStart() + i]; + + std::string name = + Reflection.StringsNonDebug[annot.GetStringNonDebug()]; + + if (annot.GetIsBuiltin()) + name = "[" + name + "]"; + else + name = "[[" + name + "]]"; + + Json.Value(name); + } }); if ((node.IsFwdBckDefined() || node.IsFwdDeclare()) || IsVerbose) { + Json.BoolField("IsFwdDeclare", node.IsFwdDeclare()); Json.BoolField("IsFwdBackDefined", node.IsFwdBckDefined()); if (node.IsFwdBckDefined() || IsVerbose) - Json.UIntField("FwdBack", node.GetFwdBck()); + Json.IntField("FwdBack", + !node.IsFwdBckDefined() ? -1 : int64_t(node.GetFwdBck())); } - if (Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { + if (hasSymbols) { - Json.Object("Symbol", [&Reflection, &Json, NodeId, IsVerbose] { + Json.Object("Symbol", [&Reflection, &Json, NodeId, IsVerbose, + AllRelevantMembers] { DxcHLSLNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; Json.StringField("Name", Reflection.Strings[sym.GetNameId()]); - if (IsVerbose) + if (IsVerbose || AllRelevantMembers) Json.UIntField("NameId", sym.GetNameId()); if (sym.HasFileSource()) { @@ -1935,7 +2081,7 @@ static void PrintNode(JsonWriter &Json, DxcHLSLReflectionData &Reflection, "Source", Reflection.Strings[Reflection.Sources[sym.GetFileSourceId()]]); - if (IsVerbose) + if (IsVerbose || AllRelevantMembers) Json.UIntField("SourceId", sym.GetFileSourceId()); Json.UIntField("LineId", sym.GetSourceLineStart()); @@ -1962,15 +2108,22 @@ static void PrintNode(JsonWriter &Json, DxcHLSLReflectionData &Reflection, } static void PrintRegister(JsonWriter &Json, DxcHLSLReflectionData &Reflection, - uint32_t RegisterId, bool IsVerbose) { + uint32_t RegisterId, bool IsVerbose, + bool AllRelevantMembers) { DxcHLSLRegister ® = Reflection.Registers[RegisterId]; JsonWriter::ObjectScope nodeRoot(Json); - Json.UIntField("RegisterId", RegisterId); - Json.UIntField("NodeId", reg.GetNodeId()); - if (Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (IsVerbose || AllRelevantMembers || !hasSymbols) { + Json.UIntField("RegisterId", RegisterId); + Json.UIntField("NodeId", reg.GetNodeId()); + } + + if (hasSymbols) Json.StringField( "Name", Reflection @@ -1992,10 +2145,14 @@ static void PrintRegister(JsonWriter &Json, DxcHLSLReflectionData &Reflection, if (reg.GetArrayId() != uint32_t(-1) || IsVerbose) { - if (IsVerbose) + if (IsVerbose || AllRelevantMembers) Json.UIntField("ArrayId", reg.GetArrayId()); Json.Array("ArraySize", [&Reflection, ®, &Json]() { + + if (reg.GetArrayId() == uint32_t(-1)) + return; + const DxcHLSLArray &arr = Reflection.Arrays[reg.GetArrayId()]; for (uint32_t i = 0; i < uint32_t(arr.ArrayElem()); ++i) @@ -2042,127 +2199,13 @@ static void PrintRegister(JsonWriter &Json, DxcHLSLReflectionData &Reflection, } } -static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, - const DxcHLSLType &Type) { - - std::string type = ""; - - if (Type.GetClass() != D3D_SVC_STRUCT && Type.GetClass() != D3D_SVC_INTERFACE_CLASS) { - - static const char *arr[] = {"void", - "bool", - "int", - "float", - "string", - NULL, - "Texture1D", - "Texture2D", - "Texture3D", - "TextureCube", - "SamplerState", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "uint", - "uint8_t", - NULL, - NULL, - NULL, - NULL, - "Buffer", - "ConstantBuffer", - NULL, - "Texture1DArray", - "Texture2DArray", - NULL, - NULL, - "Texture2DMS", - "Texture2DMSArray", - "TextureCubeArray", - NULL, - NULL, - NULL, - NULL, - "double", - "RWTexture1D", - "RWTexture1DArray", - "RWTexture2D", - "RWTexture2DArray", - "RWTexture3D", - "RWBuffer", - "ByteAddressBuffer", - "RWByteAddressBuffer", - "StructuredBuffer", - "RWStructuredBuffer", - "AppendStructuredBuffer", - "ConsumeStructuredBuffer", - "min8float", - "min10float", - "min16float", - "min12int", - "min16int", - "min16uint", - "int16_t", - "uint16_t", - "float16_t", - "int64_t", - "uint64_t"}; - - const char *ptr = arr[Type.GetType()]; - - if (ptr) - type = ptr; - } - - switch (Type.GetClass()) { - - case D3D_SVC_MATRIX_ROWS: - case D3D_SVC_VECTOR: - - type += std::to_string(Type.GetColumns()); - - if (Type.GetClass() == D3D_SVC_MATRIX_ROWS) - type += "x" + std::to_string(Type.GetRows()); - - break; - - case D3D_SVC_MATRIX_COLUMNS: - type += std::to_string(Type.GetRows()) + "x" + - std::to_string(Type.GetColumns()); - break; - } - - return type; -} - -static void FillArraySizes(DxcHLSLReflectionData &Reflection, - DxcHLSLArrayOrElements Elements, - std::vector &Array) { - - if (!Elements.IsArray()) - return; - - if (Elements.Is1DArray()) { - Array.push_back(Elements.Get1DElements()); - return; - } - - const DxcHLSLArray &arr = - Reflection.Arrays[Elements.GetMultiDimensionalArrayId()]; - - for (uint32_t i = 0; i < arr.ArrayElem(); ++i) - Array.push_back(Reflection.ArraySizes[arr.ArrayStart() + i]); -} - static void PrintTypeName(DxcHLSLReflectionData &Reflection, uint32_t TypeId, - bool HasSymbols, bool IsVerbose, JsonWriter &Json) { + bool HasSymbols, bool IsVerbose, + bool AllRelevantMembers, JsonWriter &Json, + const char *NameForTypeName = "Name") { - Json.UIntField("TypeId", TypeId); + if (AllRelevantMembers || IsVerbose || !HasSymbols) + Json.UIntField("TypeId", TypeId); std::string name; std::vector arraySizes; @@ -2186,7 +2229,7 @@ static void PrintTypeName(DxcHLSLReflectionData &Reflection, uint32_t TypeId, } if (name.size() || IsVerbose) - Json.StringField("Name", name); + Json.StringField(NameForTypeName, name); if (arraySizes.size() || IsVerbose) Json.Array("ArraySize", [&arraySizes, &Json]() { @@ -2207,15 +2250,18 @@ static void PrintTypeName(DxcHLSLReflectionData &Reflection, uint32_t TypeId, static void PrintParameter(DxcHLSLReflectionData &Reflection, uint32_t TypeId, bool HasSymbols, bool IsVerbose, JsonWriter &Json, uint32_t SemanticId, uint8_t InterpolationMode, - uint8_t Flags) { + uint8_t Flags, bool AllRelevantMembers) { - PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, Json); + PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, Json, "TypeName"); if (SemanticId != uint32_t(-1) || IsVerbose) - Json.StringField("Semantic", Reflection.StringsNonDebug[SemanticId]); + Json.StringField("Semantic", SemanticId == uint32_t(-1) + ? "" + : Reflection.StringsNonDebug[SemanticId]); - if (IsVerbose) - Json.UIntField("SemanticId", SemanticId); + if (IsVerbose || (AllRelevantMembers && SemanticId != uint32_t(-1))) + Json.IntField("SemanticId", + SemanticId == uint32_t(-1) ? -1 : int64_t(SemanticId)); if ((Flags & (D3D_PF_IN | D3D_PF_OUT)) == (D3D_PF_IN | D3D_PF_OUT)) Json.StringField("Access", "inout"); @@ -2243,18 +2289,21 @@ static void PrintParameter(DxcHLSLReflectionData &Reflection, uint32_t TypeId, } static void PrintFunction(JsonWriter &Json, DxcHLSLReflectionData &Reflection, - uint32_t FunctionId, bool IsVerbose) { + uint32_t FunctionId, bool IsVerbose, + bool AllRelevantMembers) { DxcHLSLFunction &func = Reflection.Functions[FunctionId]; JsonWriter::ObjectScope nodeRoot(Json); - Json.UIntField("FunctionId", FunctionId); - Json.UIntField("NodeId", func.GetNodeId()); - bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + if (AllRelevantMembers || IsVerbose || !hasSymbols) { + Json.UIntField("FunctionId", FunctionId); + Json.UIntField("NodeId", func.GetNodeId()); + } + if (hasSymbols) Json.StringField( "Name", @@ -2271,7 +2320,8 @@ static void PrintFunction(JsonWriter &Json, DxcHLSLReflectionData &Reflection, Json.BoolField("HasReturn", func.HasReturn()); } - Json.Object("Params", [&Reflection, &func, &Json, hasSymbols, IsVerbose]() { + Json.Object("Params", [&Reflection, &func, &Json, hasSymbols, IsVerbose, + AllRelevantMembers]() { for (uint32_t i = 0; i < uint32_t(func.GetNumParameters()); ++i) { uint32_t nodeId = func.GetNodeId() + 1 + i; @@ -2285,9 +2335,11 @@ static void PrintFunction(JsonWriter &Json, DxcHLSLReflectionData &Reflection, : std::to_string(i); Json.Object(paramName.c_str(), [&Reflection, &func, &Json, hasSymbols, - IsVerbose, ¶m, &node]() { + IsVerbose, ¶m, &node, + AllRelevantMembers]() { PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, Json, - node.GetSemanticId(), param.InterpolationMode, param.Flags); + node.GetSemanticId(), param.InterpolationMode, + param.Flags, AllRelevantMembers); }); } }); @@ -2302,9 +2354,10 @@ static void PrintFunction(JsonWriter &Json, DxcHLSLReflectionData &Reflection, const DxcHLSLParameter ¶m = Reflection.Parameters[node.GetLocalId()]; Json.Object("ReturnType", [&Reflection, &func, &Json, hasSymbols, IsVerbose, - ¶m, &node]() { + ¶m, &node, AllRelevantMembers]() { PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, Json, - node.GetSemanticId(), param.InterpolationMode, param.Flags); + node.GetSemanticId(), param.InterpolationMode, param.Flags, + AllRelevantMembers); }); } } @@ -2345,25 +2398,64 @@ static std::string ToJson(DxcHLSLReflectionData &Reflection, json.Value(Reflection.Strings[id]); }); - if (IsVerbose) - json.Array("SourcesAsId", [&Reflection, &json] { - for (uint32_t id : Reflection.Sources) - json.Value(uint64_t(id)); - }); + json.Array("SourcesAsId", [&Reflection, &json] { + for (uint32_t id : Reflection.Sources) + json.Value(uint64_t(id)); + }); json.Array("Nodes", [&Reflection, &json, IsVerbose] { for (uint32_t i = 0; i < uint32_t(Reflection.Nodes.size()); ++i) - PrintNode(json, Reflection, i, IsVerbose); + PrintNode(json, Reflection, i, IsVerbose, true); }); json.Array("Registers", [&Reflection, &json, IsVerbose] { for (uint32_t i = 0; i < uint32_t(Reflection.Registers.size()); ++i) - PrintRegister(json, Reflection, i, IsVerbose); + PrintRegister(json, Reflection, i, IsVerbose, true); }); json.Array("Functions", [&Reflection, &json, IsVerbose] { for (uint32_t i = 0; i < uint32_t(Reflection.Functions.size()); ++i) - PrintFunction(json, Reflection, i, IsVerbose); + PrintFunction(json, Reflection, i, IsVerbose, true); + }); + + // Already referenced indirectly through other properties we printed + // before, still printing it to allow consistency checks. + // For pure pretty prints, you should use the human version. + + json.Array("Parameters", [&Reflection, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Reflection.Parameters.size()); ++i) { + JsonWriter::ObjectScope nodeRoot(json); + + const DxcHLSLParameter ¶m = Reflection.Parameters[i]; + std::string paramName = + hasSymbols + ? Reflection.Strings[Reflection.NodeSymbols[param.NodeId] + .GetNameId()] + : std::to_string(i); + + json.StringField("ParamName", paramName); + + PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, json, + Reflection.Nodes[param.NodeId].GetSemanticId(), + param.InterpolationMode, param.Flags, true); + } + }); + + // TODO: Arrays + + json.Array("ArraySizes", [&Reflection, &json] { + for (uint32_t id : Reflection.ArraySizes) + json.Value(uint64_t(id)); + }); + + json.Array("MemberTypeIds", [&Reflection, &json] { + for (uint32_t id : Reflection.MemberTypeIds) + json.Value(uint64_t(id)); + }); + + json.Array("TypeList", [&Reflection, &json] { + for (uint32_t id : Reflection.TypeList) + json.Value(uint64_t(id)); }); } From 0217b6d5ac3117d168d4ee158cac490bcb09bff5 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 15:50:14 +0100 Subject: [PATCH 072/126] Added printing Enum values/descs, annotations, arrays and started on statements. TypeList and MemberTypeIds now properly print type info. TODO: Added a stub for statements, need to add buffers and full types and need to add names to member types. Then add a human readable version, while the other is meant for 1:1 data inspection. --- tools/clang/tools/libclang/dxcreflector.cpp | 163 +++++++++++++++++++- 1 file changed, 155 insertions(+), 8 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 33499cb97b..03052ee7ee 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1874,6 +1874,15 @@ static const char *ReturnTypeToString(D3D_RESOURCE_RETURN_TYPE Type) { return arr[uint32_t(Type)]; } +static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { + + static const char *arr[] = { + "uint", "int", "uint64_t", "int64_t", "uint16_t", "int16_t", + }; + + return arr[type]; +} + static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, const DxcHLSLType &Type) { @@ -2240,7 +2249,7 @@ static void PrintTypeName(DxcHLSLReflectionData &Reflection, uint32_t TypeId, if (underlyingName.size() || IsVerbose) Json.StringField("UnderlyingName", underlyingName); - if (underlyingArraySizes.size() || IsVerbose) + if ((underlyingArraySizes.size() && underlyingArraySizes != arraySizes) || IsVerbose) Json.Array("UnderlyingArraySize", [&underlyingArraySizes, &Json]() { for (uint32_t i : underlyingArraySizes) Json.Value(uint64_t(i)); @@ -2362,6 +2371,88 @@ static void PrintFunction(JsonWriter &Json, DxcHLSLReflectionData &Reflection, } } +static void PrintEnumValue(JsonWriter &Json, DxcHLSLReflectionData &Reflection, + uint32_t ChildId, bool IsVerbose, + bool AllRelevantMembers) { + + const DxcHLSLNode &child = Reflection.Nodes[ChildId]; + + const DxcHLSLEnumValue &val = Reflection.EnumValues[child.GetLocalId()]; + + const DxcHLSLNode &parent = Reflection.Nodes[child.GetParentId()]; + const DxcHLSLEnumDesc &enm = Reflection.Enums[parent.GetLocalId()]; + + switch (enm.Type) { + case D3D12_HLSL_ENUM_TYPE_INT: + case D3D12_HLSL_ENUM_TYPE_INT64_T: + case D3D12_HLSL_ENUM_TYPE_INT16_T: + Json.IntField("Value", val.Value); + break; + + default: + Json.UIntField("Value", uint64_t(val.Value)); + } + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (hasSymbols || IsVerbose) + Json.StringField( + "Name", + !hasSymbols + ? "" + : Reflection.Strings[Reflection.NodeSymbols[ChildId].GetNameId()]); +} + +static void PrintEnum(JsonWriter &Json, DxcHLSLReflectionData &Reflection, + uint32_t EnumId, bool IsVerbose, + bool AllRelevantMembers) { + + JsonWriter::ObjectScope nodeRoot(Json); + const DxcHLSLEnumDesc &enm = Reflection.Enums[EnumId]; + const DxcHLSLNode &node = Reflection.Nodes[enm.NodeId]; + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (AllRelevantMembers || IsVerbose || !hasSymbols) { + Json.UIntField("EnumId", EnumId); + Json.UIntField("NodeId", enm.NodeId); + } + + if (hasSymbols) + Json.StringField( + "Name", + Reflection.Strings[Reflection.NodeSymbols[enm.NodeId].GetNameId()]); + + else if (IsVerbose) + Json.StringField("Name", ""); + + Json.StringField("EnumType", EnumTypeToString(enm.Type)); + + Json.Array("Values", [&Json, &node, &enm, hasSymbols, &Reflection, IsVerbose, + AllRelevantMembers]() { + for (uint32_t i = 0; i < node.GetChildCount(); ++i) { + + uint32_t childId = enm.NodeId + 1 + i; + + JsonWriter::ObjectScope valueRoot(Json); + + if (!hasSymbols || AllRelevantMembers || IsVerbose) + Json.UIntField("ValueId", i); + + PrintEnumValue(Json, Reflection, childId, IsVerbose, AllRelevantMembers); + } + }); +} + +static void PrintAnnotation(JsonWriter &Json, DxcHLSLReflectionData &Reflection, + const DxcHLSLAnnotation &Annot) { + Json.StringField("Contents", + Reflection.StringsNonDebug[Annot.GetStringNonDebug()]); + Json.StringField("Type", Annot.GetIsBuiltin() ? "Builtin" : "User"); +} + //IsHumanFriendly = false: Raw view of the real file data //IsHumanFriendly = true: Clean view that's relatively close to the real tree static std::string ToJson(DxcHLSLReflectionData &Reflection, @@ -2441,21 +2532,77 @@ static std::string ToJson(DxcHLSLReflectionData &Reflection, } }); - // TODO: Arrays + json.Array("Enums", [&Reflection, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Reflection.Enums.size()); ++i) + PrintEnum(json, Reflection, i, IsVerbose, true); + }); + + json.Array("EnumValues", [&Reflection, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Reflection.EnumValues.size()); ++i) { + JsonWriter::ObjectScope valueRoot(json); + PrintEnumValue(json, Reflection, Reflection.EnumValues[i].NodeId, + IsVerbose, true); + } + }); + + json.Array("Annotations", [&Reflection, &json, hasSymbols] { + for (uint32_t i = 0; i < uint32_t(Reflection.Annotations.size()); ++i) { + const DxcHLSLAnnotation &annot = Reflection.Annotations[i]; + JsonWriter::ObjectScope valueRoot(json); + json.UIntField("StringId", annot.GetStringNonDebug()); + PrintAnnotation(json, Reflection, annot); + } + }); + + json.Array("Arrays", [&Reflection, &json] { + for (uint32_t i = 0; i < uint32_t(Reflection.Arrays.size()); ++i) { + const DxcHLSLArray &arr = Reflection.Arrays[i]; + JsonWriter::ObjectScope valueRoot(json); + json.UIntField("ArrayElem", arr.ArrayElem()); + json.UIntField("ArrayStart", arr.ArrayStart()); + json.Array("ArraySizes", [&Reflection, &json, &arr] { + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) { + json.Value(uint64_t(Reflection.ArraySizes[arr.ArrayStart() + i])); + } + }); + } + }); json.Array("ArraySizes", [&Reflection, &json] { for (uint32_t id : Reflection.ArraySizes) json.Value(uint64_t(id)); }); - json.Array("MemberTypeIds", [&Reflection, &json] { - for (uint32_t id : Reflection.MemberTypeIds) - json.Value(uint64_t(id)); + /*json.Array("Statements", [&Reflection, &json] { + for (uint32_t i = 0; i < uint32_t(Reflection.Statements.size()); ++i) { + + const DxcHLSLStatement &stat = Reflection.Statements[i]; + JsonWriter::ObjectScope valueRoot(json); + json.UIntField("Type", annot.GetStringNonDebug()); + json.UIntField("NodeId", annot.GetStringNonDebug()); + + PrintStatement(json, Reflection, stat); + } + });*/ + + //TODO: buffers + + //TODO: Type to combine type and type symbol + + //TODO: members to combine memberTypeIds and memberNameIds + + json.Array("MemberTypeIds", [&Reflection, &json, hasSymbols, IsVerbose] { + for (uint32_t id : Reflection.MemberTypeIds) { + JsonWriter::ObjectScope valueRoot(json); + PrintTypeName(Reflection, id, hasSymbols, IsVerbose, true, json); + } }); - json.Array("TypeList", [&Reflection, &json] { - for (uint32_t id : Reflection.TypeList) - json.Value(uint64_t(id)); + json.Array("TypeList", [&Reflection, &json, hasSymbols, IsVerbose] { + for (uint32_t id : Reflection.TypeList) { + JsonWriter::ObjectScope valueRoot(json); + PrintTypeName(Reflection, id, hasSymbols, IsVerbose, true, json); + } }); } From 3388dd52a60b8704942dd581dadbcb9d1e48ee77 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 16:28:57 +0100 Subject: [PATCH 073/126] Now handling type printing --- tools/clang/tools/libclang/dxcreflector.cpp | 86 ++++++++++++++++++--- 1 file changed, 77 insertions(+), 9 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 03052ee7ee..4c6ba9034f 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1791,7 +1791,6 @@ struct JsonWriter { ValueNull(); EndCommaStack(); } - }; void PrintFeatures(D3D12_HLSL_REFLECTION_FEATURE Features, JsonWriter &Json) { @@ -2246,7 +2245,7 @@ static void PrintTypeName(DxcHLSLReflectionData &Reflection, uint32_t TypeId, Json.Value(uint64_t(i)); }); - if (underlyingName.size() || IsVerbose) + if ((underlyingName.size() && underlyingName != name) || IsVerbose) Json.StringField("UnderlyingName", underlyingName); if ((underlyingArraySizes.size() && underlyingArraySizes != arraySizes) || IsVerbose) @@ -2256,6 +2255,64 @@ static void PrintTypeName(DxcHLSLReflectionData &Reflection, uint32_t TypeId, }); } +static void PrintType(DxcHLSLReflectionData &Reflection, uint32_t TypeId, + bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, + JsonWriter &Json) { + + const DxcHLSLType &type = Reflection.Types[TypeId]; + + JsonWriter::ObjectScope nodeRoot(Json); + PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, + Json); + + if (type.GetBaseClass() != uint32_t(-1)) + Json.Object("BaseClass", [&Reflection, &Json, &type, HasSymbols, IsVerbose, + AllRelevantMembers]() { + PrintTypeName(Reflection, type.GetBaseClass(), HasSymbols, IsVerbose, + AllRelevantMembers, Json); + }); + + else if (IsVerbose) + Json.NullField("BaseClass"); + + if (type.GetInterfaceCount()) + Json.Array("Interfaces", [&Reflection, &Json, &type, HasSymbols, IsVerbose, + AllRelevantMembers]() { + for (uint32_t i = 0; i < uint32_t(type.GetInterfaceCount()); ++i) { + uint32_t interfaceId = type.GetInterfaceStart() + i; + JsonWriter::ObjectScope nodeRoot(Json); + PrintTypeName(Reflection, Reflection.TypeList[interfaceId], HasSymbols, + IsVerbose, AllRelevantMembers, Json); + } + }); + + else if (IsVerbose) + Json.NullField("Interfaces"); + + if (type.GetMemberCount()) + Json.Array("Members", [&Reflection, &Json, &type, HasSymbols, IsVerbose, + AllRelevantMembers]() { + for (uint32_t i = 0; i < uint32_t(type.GetMemberCount()); ++i) { + + uint32_t memberId = type.GetMemberStart() + i; + JsonWriter::ObjectScope nodeRoot(Json); + + if (HasSymbols) { + Json.StringField( + "Name", Reflection.Strings[Reflection.MemberNameIds[memberId]]); + Json.UIntField("NameId", Reflection.MemberNameIds[memberId]); + } + + PrintTypeName(Reflection, Reflection.MemberTypeIds[memberId], + HasSymbols, IsVerbose, AllRelevantMembers, Json, + "TypeName"); + } + }); + + else if (IsVerbose) + Json.NullField("Members"); +} + static void PrintParameter(DxcHLSLReflectionData &Reflection, uint32_t TypeId, bool HasSymbols, bool IsVerbose, JsonWriter &Json, uint32_t SemanticId, uint8_t InterpolationMode, @@ -2585,16 +2642,20 @@ static std::string ToJson(DxcHLSLReflectionData &Reflection, } });*/ - //TODO: buffers + json.Array("Members", [&Reflection, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Reflection.MemberTypeIds.size()); + ++i) { - //TODO: Type to combine type and type symbol + JsonWriter::ObjectScope valueRoot(json); - //TODO: members to combine memberTypeIds and memberNameIds + if (hasSymbols) { + json.StringField("Name", + Reflection.Strings[Reflection.MemberNameIds[i]]); + json.UIntField("NameId", Reflection.MemberNameIds[i]); + } - json.Array("MemberTypeIds", [&Reflection, &json, hasSymbols, IsVerbose] { - for (uint32_t id : Reflection.MemberTypeIds) { - JsonWriter::ObjectScope valueRoot(json); - PrintTypeName(Reflection, id, hasSymbols, IsVerbose, true, json); + PrintTypeName(Reflection, Reflection.MemberTypeIds[i], hasSymbols, + IsVerbose, true, json, "TypeName"); } }); @@ -2604,6 +2665,13 @@ static std::string ToJson(DxcHLSLReflectionData &Reflection, PrintTypeName(Reflection, id, hasSymbols, IsVerbose, true, json); } }); + + json.Array("Types", [&Reflection, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Reflection.Types.size()); ++i) + PrintType(Reflection, i, hasSymbols, IsVerbose, true, json); + }); + + // TODO: buffers } else { From 96158ba9074ead99d2cd956e6b759fadef8581ce Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 17:09:55 +0100 Subject: [PATCH 074/126] Implemented recursive buffer printing --- tools/clang/tools/libclang/dxcreflector.cpp | 146 ++++++++++++++++++-- 1 file changed, 131 insertions(+), 15 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 4c6ba9034f..960316ed97 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1873,13 +1873,18 @@ static const char *ReturnTypeToString(D3D_RESOURCE_RETURN_TYPE Type) { return arr[uint32_t(Type)]; } -static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE type) { +static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE Type) { static const char *arr[] = { "uint", "int", "uint64_t", "int64_t", "uint16_t", "int16_t", }; - return arr[type]; + return arr[Type]; +} + +static std::string BufferTypeToString(D3D_CBUFFER_TYPE Type) { + static const char *arr[] = {"cbuffer", "tbuffer", "undefined", "structured"}; + return arr[Type]; } static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, @@ -2510,6 +2515,114 @@ static void PrintAnnotation(JsonWriter &Json, DxcHLSLReflectionData &Reflection, Json.StringField("Type", Annot.GetIsBuiltin() ? "Builtin" : "User"); } +static void PrintBufferMemberMember(DxcHLSLReflectionData &Reflection, + bool HasSymbols, bool IsVerbose, + bool AllRelevantMembers, JsonWriter &Json, + uint32_t ChildId, uint32_t MemberId) { + + uint32_t TypeId = Reflection.MemberTypeIds[MemberId]; + + JsonWriter::ObjectScope nodeRoot(Json); + + if (IsVerbose || AllRelevantMembers || !HasSymbols) + Json.UIntField("ChildId", ChildId); + + if (HasSymbols) + Json.StringField("Name", + Reflection.Strings[Reflection.MemberNameIds[MemberId]]); + + else if (IsVerbose) + Json.StringField("Name", ""); + + const DxcHLSLType &type = Reflection.Types[TypeId]; + + PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, + Json, "TypeName"); + + if (type.GetMemberCount()) + Json.Array("Children", [&type, &Reflection, &Json, HasSymbols, IsVerbose, + AllRelevantMembers]() { + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { + + uint32_t memberId = type.GetMemberStart() + i; + + PrintBufferMemberMember(Reflection, HasSymbols, IsVerbose, + AllRelevantMembers, Json, i, memberId); + } + }); +} + +static uint32_t PrintBufferMember(DxcHLSLReflectionData &Reflection, + uint32_t NodeId, bool HasSymbols, + bool IsVerbose, bool AllRelevantMembers, + JsonWriter &Json) { + + const DxcHLSLNode &node = Reflection.Nodes[NodeId]; + + JsonWriter::ObjectScope root(Json); + + if (IsVerbose || AllRelevantMembers || !HasSymbols) + Json.UIntField("NodeId", NodeId); + + if (HasSymbols) + Json.StringField( + "Name", Reflection.Strings[Reflection.NodeSymbols[NodeId].GetNameId()]); + + else if (IsVerbose) + Json.StringField("Name", ""); + + PrintTypeName(Reflection, node.GetLocalId(), HasSymbols, IsVerbose, + AllRelevantMembers, Json, "TypeName"); + + const DxcHLSLType &type = Reflection.Types[node.GetLocalId()]; + + if (type.GetMemberCount() || IsVerbose) + Json.Array("Children", [&type, &Reflection, &Json, HasSymbols, IsVerbose, + AllRelevantMembers]() { + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) + PrintBufferMemberMember(Reflection, HasSymbols, IsVerbose, + AllRelevantMembers, Json, i, + type.GetMemberStart() + i); + }); + + return node.GetChildCount(); +} + +static void PrintBuffer(DxcHLSLReflectionData &Reflection, uint32_t BufferId, + bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, + JsonWriter &Json) { + + JsonWriter::ObjectScope nodeRoot(Json); + const DxcHLSLBuffer &buf = Reflection.Buffers[BufferId]; + const DxcHLSLNode &node = Reflection.Nodes[buf.NodeId]; + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (AllRelevantMembers || IsVerbose || !hasSymbols) { + Json.UIntField("BufferId", BufferId); + Json.UIntField("NodeId", buf.NodeId); + } + + if (hasSymbols) + Json.StringField( + "Name", + Reflection.Strings[Reflection.NodeSymbols[buf.NodeId].GetNameId()]); + + else if (IsVerbose) + Json.StringField("Name", ""); + + Json.StringField("Type", BufferTypeToString(buf.Type)); + + if (node.GetChildCount() || IsVerbose) + Json.Array("Children", [&node, &Reflection, &buf, &Json, HasSymbols, + IsVerbose, AllRelevantMembers]() { + for (uint32_t i = 0; i < node.GetChildCount(); ++i) + i += PrintBufferMember(Reflection, buf.NodeId + 1 + i, HasSymbols, + IsVerbose, AllRelevantMembers, Json); + }); +} + //IsHumanFriendly = false: Raw view of the real file data //IsHumanFriendly = true: Clean view that's relatively close to the real tree static std::string ToJson(DxcHLSLReflectionData &Reflection, @@ -2630,18 +2743,6 @@ static std::string ToJson(DxcHLSLReflectionData &Reflection, json.Value(uint64_t(id)); }); - /*json.Array("Statements", [&Reflection, &json] { - for (uint32_t i = 0; i < uint32_t(Reflection.Statements.size()); ++i) { - - const DxcHLSLStatement &stat = Reflection.Statements[i]; - JsonWriter::ObjectScope valueRoot(json); - json.UIntField("Type", annot.GetStringNonDebug()); - json.UIntField("NodeId", annot.GetStringNonDebug()); - - PrintStatement(json, Reflection, stat); - } - });*/ - json.Array("Members", [&Reflection, &json, hasSymbols, IsVerbose] { for (uint32_t i = 0; i < uint32_t(Reflection.MemberTypeIds.size()); ++i) { @@ -2671,7 +2772,22 @@ static std::string ToJson(DxcHLSLReflectionData &Reflection, PrintType(Reflection, i, hasSymbols, IsVerbose, true, json); }); - // TODO: buffers + json.Array("Buffers", [&Reflection, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Reflection.Buffers.size()); ++i) + PrintBuffer(Reflection, i, hasSymbols, IsVerbose, true, json); + }); + + /*json.Array("Statements", [&Reflection, &json] { + for (uint32_t i = 0; i < uint32_t(Reflection.Statements.size()); ++i) { + + const DxcHLSLStatement &stat = Reflection.Statements[i]; + JsonWriter::ObjectScope valueRoot(json); + json.UIntField("Type", annot.GetStringNonDebug()); + json.UIntField("NodeId", annot.GetStringNonDebug()); + + PrintStatement(json, Reflection, stat); + } + });*/ } else { From 48eebe2eb0075eac1a5e42e5bcef274f5cfbdbec Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 17:31:19 +0100 Subject: [PATCH 075/126] Completed statements to string --- tools/clang/tools/libclang/dxcreflector.cpp | 35 ++++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 960316ed97..3ae5f7d050 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -2623,6 +2623,29 @@ static void PrintBuffer(DxcHLSLReflectionData &Reflection, uint32_t BufferId, }); } +static void PrintStatement(DxcHLSLReflectionData &Reflection, + const DxcHLSLStatement &Stmt, JsonWriter &Json, + bool IsVerbose) { + + const DxcHLSLNode &node = Reflection.Nodes[Stmt.GetNodeId()]; + + uint32_t nodesA = Stmt.GetNodeCount(); + uint32_t nodesB = node.GetChildCount() - nodesA - Stmt.HasConditionVar(); + + Json.BoolField("HasConditionVar", Stmt.HasConditionVar()); + + bool isIf = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF; + + if (isIf || IsVerbose) + Json.BoolField("HasElse", Stmt.HasElse()); + + if (nodesA || IsVerbose) + Json.UIntField("NodesA", nodesA); + + if (nodesB || IsVerbose) + Json.UIntField("NodesB", nodesB); +} + //IsHumanFriendly = false: Raw view of the real file data //IsHumanFriendly = true: Clean view that's relatively close to the real tree static std::string ToJson(DxcHLSLReflectionData &Reflection, @@ -2777,17 +2800,19 @@ static std::string ToJson(DxcHLSLReflectionData &Reflection, PrintBuffer(Reflection, i, hasSymbols, IsVerbose, true, json); }); - /*json.Array("Statements", [&Reflection, &json] { + json.Array("Statements", [&Reflection, &json, IsVerbose] { for (uint32_t i = 0; i < uint32_t(Reflection.Statements.size()); ++i) { const DxcHLSLStatement &stat = Reflection.Statements[i]; JsonWriter::ObjectScope valueRoot(json); - json.UIntField("Type", annot.GetStringNonDebug()); - json.UIntField("NodeId", annot.GetStringNonDebug()); + json.StringField( + "Type", NodeTypeToString( + Reflection.Nodes[stat.GetNodeId()].GetNodeType())); + json.UIntField("NodeId", stat.GetNodeId()); - PrintStatement(json, Reflection, stat); + PrintStatement(Reflection, stat, json, IsVerbose); } - });*/ + }); } else { From cfb5c7b2855ea5ec212240c547e1e53b4d92cb93 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 17:50:05 +0100 Subject: [PATCH 076/126] Moved json serialization to DxcReflectionJson.cpp in the reflection api, so it can be used by anyone --- include/dxc/DxcReflection/DxcReflection.h | 1 + .../clang/tools/dxcreflection/CMakeLists.txt | 2 +- .../tools/dxcreflection/DxcReflectionJson.cpp | 1287 +++++++++++++++++ tools/clang/tools/libclang/dxcreflector.cpp | 1280 +--------------- 4 files changed, 1291 insertions(+), 1279 deletions(-) create mode 100644 tools/clang/tools/dxcreflection/DxcReflectionJson.cpp diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 8e7621bf8c..9bd006ace7 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -828,6 +828,7 @@ struct DxcHLSLReflectionData { static D3D_CBUFFER_TYPE GetBufferType(uint8_t Type); void Dump(std::vector &Bytes) const; + std::string ToJson(bool IsHumanFriendly = true, bool IsVerbose = false) const; void StripSymbols(); bool GenerateNameLookupTable(); diff --git a/tools/clang/tools/dxcreflection/CMakeLists.txt b/tools/clang/tools/dxcreflection/CMakeLists.txt index 2d4510609a..dc54faa64f 100644 --- a/tools/clang/tools/dxcreflection/CMakeLists.txt +++ b/tools/clang/tools/dxcreflection/CMakeLists.txt @@ -1,4 +1,4 @@ # Copyright (C) Microsoft Corporation. All rights reserved. # This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. -add_clang_library(dxcreflection STATIC DxcReflection.cpp) +add_clang_library(dxcreflection STATIC DxcReflection.cpp DxcReflectionJson.cpp) diff --git a/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp new file mode 100644 index 0000000000..0eb7aa5d07 --- /dev/null +++ b/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp @@ -0,0 +1,1287 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// DxcReflectionJson.cpp // +// Copyright (C) Microsoft Corporation. All rights reserved. // +// This file is distributed under the University of Illinois Open Source // +// License. See LICENSE.TXT for details. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include "dxc/DxcReflection/DxcReflection.h" +#include +#include + +namespace hlsl { + +struct JsonWriter { + + std::stringstream ss; + uint16_t indent = 0; + uint16_t countCommaStack = 0; + uint32_t needCommaStack = 0; + + void Indent() { ss << std::string(indent, '\t'); } + void NewLine() { ss << "\n"; } + + void StartCommaStack() { + ++countCommaStack; + assert(countCommaStack < 32 && "countCommaStack out of bounds"); + needCommaStack &= ~(1u << countCommaStack); + } + + void SetComma() { needCommaStack |= 1u << countCommaStack; } + + void EndCommaStack() { + --countCommaStack; + SetComma(); + } + + bool NeedsComma() { return (needCommaStack >> countCommaStack) & 1; } + + void BeginObj() { + + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + + ss << "{\n"; + ++indent; + StartCommaStack(); + Indent(); + } + + void EndObj() { + ss << "\n"; + --indent; + Indent(); + ss << "}"; + EndCommaStack(); + } + + void BeginArray(const char *Name) { + + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + + if (Name) { + StartCommaStack(); + Key(Name); + --countCommaStack; + } + + ss << "[\n"; + ++indent; + StartCommaStack(); + Indent(); + } + + void EndArray() { + ss << "\n"; + --indent; + Indent(); + ss << "]"; + EndCommaStack(); + } + + void Key(const char *Key) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << "\"" << Escape(Key) << "\": "; + } + + void Value(std::string S) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << "\"" << Escape(S) << "\""; + SetComma(); + } + + void Value(const char *S) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << "\"" << S << "\""; + SetComma(); + } + + void ValueNull() { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << "null"; + SetComma(); + } + + void Value(uint64_t V) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << V; + SetComma(); + } + + void Value(int64_t V) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << V; + SetComma(); + } + + void Value(bool V) { + if (NeedsComma()) { + ss << ",\n"; + Indent(); + } + ss << (V ? "true" : "false"); + SetComma(); + } + + static std::string Escape(const std::string &In) { + std::string out; + out.reserve(In.size()); + for (char c : In) { + switch (c) { + case '\\': + out += "\\\\"; + break; + case '"': + out += "\\\""; + break; + case '\n': + out += "\\n"; + break; + case '\r': + out += "\\r"; + break; + case '\t': + out += "\\t"; + break; + default: + out += c; + break; + } + } + return out; + } + + std::string str() const { return ss.str(); } + + struct ObjectScope { + + JsonWriter &W; + bool NeedsEndCommaStack; + + ObjectScope(JsonWriter &W, const char *Name = nullptr) + : W(W), NeedsEndCommaStack(Name) { + + if (Name) { + W.Key(Name); + W.StartCommaStack(); + } + + W.BeginObj(); + } + + ~ObjectScope() { + W.EndObj(); + + if (NeedsEndCommaStack) + W.EndCommaStack(); + } + }; + + struct ArrayScope { + JsonWriter &W; + ArrayScope(JsonWriter &W, const char *Name = nullptr) : W(W) { + W.BeginArray(Name); + } + ~ArrayScope() { W.EndArray(); } + }; + + void Object(const char *Name, const std::function &Body) { + ObjectScope _(*this, Name); + Body(); + } + + void Array(const char *Name, const std::function &Body) { + ArrayScope _( *this, Name ); Body(); + } + + void StringField(const char *K, const std::string &V) { + Key(K); + StartCommaStack(); + Value(V); + EndCommaStack(); + } + + void UIntField(const char *K, uint64_t V) { + Key(K); + StartCommaStack(); + Value(V); + EndCommaStack(); + } + + void IntField(const char *K, int64_t V) { + Key(K); + StartCommaStack(); + Value(V); + EndCommaStack(); + } + + void BoolField(const char *K, bool V) { + Key(K); + StartCommaStack(); + Value(V); + EndCommaStack(); + } + + void NullField(const char *K) { + Key(K); + StartCommaStack(); + ValueNull(); + EndCommaStack(); + } +}; + +void PrintFeatures(D3D12_HLSL_REFLECTION_FEATURE Features, JsonWriter &Json) { + Json.Array("Features", [Features, &Json] { + if (Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS) + Json.Value("Basics"); + if (Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS) + Json.Value("Functions"); + if (Features & D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES) + Json.Value("Namespaces"); + if (Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES) + Json.Value("UserTypes"); + if (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES) + Json.Value("Scopes"); + if (Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + Json.Value("Symbols"); + }); +} + +static const char *NodeTypeToString(D3D12_HLSL_NODE_TYPE Type) { + + static const char *arr[] = {"Register", + "Function", + "Enum", + "EnumValue", + "Namespace", + "Variable", + "Typedef", + "Struct", + "Union", + "StaticVariable", + "Interface", + "Parameter", + "If", + "Scope", + "Do", + "Switch", + "While", + "For", + "GroupsharedVariable"}; + + return arr[uint32_t(Type)]; +} + +static const char *RegisterTypeToString(D3D_SHADER_INPUT_TYPE Type) { + + static const char *arr[] = {"cbuffer", + "tbuffer", + "Texture", + "SamplerState", + "RWTexture", + "StructuredBuffer", + "RWStructuredBuffer", + "ByteAddressBuffer", + "RWByteAddressBuffer", + "AppendStructuredBuffer", + "ConsumeStructuredBuffer", + "(Append/Consume)StructuredBuffer", + "RaytracingAccelerationStructure", + "FeedbackTexture"}; + + return arr[uint32_t(Type)]; +} + +static const char *DimensionTypeToString(D3D_SRV_DIMENSION Type) { + + static const char *arr[] = { + "Unknown", "Buffer", "Texture1D", "Texture1DArray", + "Texture2D", "Texture2DArray", "Texture2DMS", "Texture2DMSArray", + "Texture3D", "TextureCube", "TextureCubeArray", "BufferEx"}; + + return arr[uint32_t(Type)]; +} + +static const char *ReturnTypeToString(D3D_RESOURCE_RETURN_TYPE Type) { + + static const char *arr[] = {"unknown", "unorm", "snorm", "sint", "uint", + "float", "mixed", "double", "continued"}; + + return arr[uint32_t(Type)]; +} + +static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE Type) { + + static const char *arr[] = { + "uint", "int", "uint64_t", "int64_t", "uint16_t", "int16_t", + }; + + return arr[Type]; +} + +static std::string BufferTypeToString(D3D_CBUFFER_TYPE Type) { + static const char *arr[] = {"cbuffer", "tbuffer", "undefined", "structured"}; + return arr[Type]; +} + +static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, + const DxcHLSLType &Type) { + + std::string type = ""; + + if (Type.GetClass() != D3D_SVC_STRUCT && Type.GetClass() != D3D_SVC_INTERFACE_CLASS) { + + static const char *arr[] = {"void", + "bool", + "int", + "float", + "string", + NULL, + "Texture1D", + "Texture2D", + "Texture3D", + "TextureCube", + "SamplerState", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "uint", + "uint8_t", + NULL, + NULL, + NULL, + NULL, + "Buffer", + "ConstantBuffer", + NULL, + "Texture1DArray", + "Texture2DArray", + NULL, + NULL, + "Texture2DMS", + "Texture2DMSArray", + "TextureCubeArray", + NULL, + NULL, + NULL, + NULL, + "double", + "RWTexture1D", + "RWTexture1DArray", + "RWTexture2D", + "RWTexture2DArray", + "RWTexture3D", + "RWBuffer", + "ByteAddressBuffer", + "RWByteAddressBuffer", + "StructuredBuffer", + "RWStructuredBuffer", + "AppendStructuredBuffer", + "ConsumeStructuredBuffer", + "min8float", + "min10float", + "min16float", + "min12int", + "min16int", + "min16uint", + "int16_t", + "uint16_t", + "float16_t", + "int64_t", + "uint64_t"}; + + const char *ptr = arr[Type.GetType()]; + + if (ptr) + type = ptr; + } + + switch (Type.GetClass()) { + + case D3D_SVC_MATRIX_ROWS: + case D3D_SVC_VECTOR: + + type += std::to_string(Type.GetColumns()); + + if (Type.GetClass() == D3D_SVC_MATRIX_ROWS) + type += "x" + std::to_string(Type.GetRows()); + + break; + + case D3D_SVC_MATRIX_COLUMNS: + type += std::to_string(Type.GetRows()) + "x" + + std::to_string(Type.GetColumns()); + break; + } + + return type; +} + +static void FillArraySizes(const DxcHLSLReflectionData &Reflection, + DxcHLSLArrayOrElements Elements, + std::vector &Array) { + + if (!Elements.IsArray()) + return; + + if (Elements.Is1DArray()) { + Array.push_back(Elements.Get1DElements()); + return; + } + + const DxcHLSLArray &arr = + Reflection.Arrays[Elements.GetMultiDimensionalArrayId()]; + + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) + Array.push_back(Reflection.ArraySizes[arr.ArrayStart() + i]); +} + +//Verbose and all members are slightly different; +//Verbose will still print fields even if they aren't relevant, +// while all members will not silence important info but that might not matter for human readability +static void PrintNode(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, + uint32_t NodeId, bool IsVerbose, bool AllRelevantMembers) { + + const DxcHLSLNode &node = Reflection.Nodes[NodeId]; + + JsonWriter::ObjectScope nodeRoot(Json); + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (AllRelevantMembers || IsVerbose || !hasSymbols) + Json.UIntField("NodeId", NodeId); + + Json.StringField("NodeType", NodeTypeToString(node.GetNodeType())); + + if (IsVerbose || AllRelevantMembers) { + Json.UIntField("NodeTypeId", node.GetNodeType()); + Json.UIntField("LocalId", node.GetLocalId()); + Json.IntField("ParentId", node.GetParentId() == uint16_t(-1) + ? -1 + : int64_t(node.GetParentId())); + } + + if (IsVerbose || (node.GetChildCount() && AllRelevantMembers)) { + Json.UIntField("ChildCount", node.GetChildCount()); + Json.UIntField("ChildStart", NodeId + 1); + } + + if (node.GetSemanticId() != uint32_t(-1) || IsVerbose) + Json.StringField("Semantic", + node.GetSemanticId() != uint32_t(-1) + ? Reflection.StringsNonDebug[node.GetSemanticId()] + : ""); + + if (IsVerbose || (AllRelevantMembers && node.GetSemanticId() != uint32_t(-1))) + Json.IntField("SemanticId", node.GetSemanticId() == uint32_t(-1) ? -1 : int64_t(node.GetSemanticId())); + + if (IsVerbose || (AllRelevantMembers && node.GetAnnotationCount())) { + Json.UIntField("AnnotationStart", node.GetAnnotationStart()); + Json.UIntField("AnnotationCount", node.GetAnnotationCount()); + } + + if (node.GetAnnotationCount() || IsVerbose) + Json.Array("Annotations", [&Reflection, &Json, node] { + for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) { + + const DxcHLSLAnnotation &annot = + Reflection.Annotations[node.GetAnnotationStart() + i]; + + std::string name = + Reflection.StringsNonDebug[annot.GetStringNonDebug()]; + + if (annot.GetIsBuiltin()) + name = "[" + name + "]"; + else + name = "[[" + name + "]]"; + + Json.Value(name); + } + }); + + if ((node.IsFwdBckDefined() || node.IsFwdDeclare()) || IsVerbose) { + + Json.BoolField("IsFwdDeclare", node.IsFwdDeclare()); + Json.BoolField("IsFwdBackDefined", node.IsFwdBckDefined()); + + if (node.IsFwdBckDefined() || IsVerbose) + Json.IntField("FwdBack", + !node.IsFwdBckDefined() ? -1 : int64_t(node.GetFwdBck())); + } + + if (hasSymbols) { + + Json.Object("Symbol", [&Reflection, &Json, NodeId, IsVerbose, + AllRelevantMembers] { + const DxcHLSLNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; + Json.StringField("Name", Reflection.Strings[sym.GetNameId()]); + + if (IsVerbose || AllRelevantMembers) + Json.UIntField("NameId", sym.GetNameId()); + + if (sym.HasFileSource()) { + + Json.StringField( + "Source", + Reflection.Strings[Reflection.Sources[sym.GetFileSourceId()]]); + + if (IsVerbose || AllRelevantMembers) + Json.UIntField("SourceId", sym.GetFileSourceId()); + + Json.UIntField("LineId", sym.GetSourceLineStart()); + Json.UIntField("LineCount", sym.GetSourceLineCount()); + + Json.UIntField("ColumnStart", sym.GetSourceColumnStart()); + Json.UIntField("ColumnEnd", sym.GetSourceColumnEnd()); + + } else if (IsVerbose) { + + Json.StringField("Source", ""); + Json.IntField("SourceId", -1); + + Json.IntField("LineId", -1); + Json.UIntField("LineCount", 0); + + Json.IntField("ColumnStart", -1); + Json.UIntField("ColumnEnd", 0); + } + }); + + } else if (IsVerbose) + Json.NullField("Symbol"); +} + +static void PrintRegister(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, + uint32_t RegisterId, bool IsVerbose, + bool AllRelevantMembers) { + + const DxcHLSLRegister ® = Reflection.Registers[RegisterId]; + + JsonWriter::ObjectScope nodeRoot(Json); + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (IsVerbose || AllRelevantMembers || !hasSymbols) { + Json.UIntField("RegisterId", RegisterId); + Json.UIntField("NodeId", reg.GetNodeId()); + } + + if (hasSymbols) + Json.StringField( + "Name", + Reflection + .Strings[Reflection.NodeSymbols[reg.GetNodeId()].GetNameId()]); + + else if (IsVerbose) + Json.StringField("Name", ""); + + Json.StringField("RegisterType", RegisterTypeToString(reg.GetType())); + + if (reg.GetDimension() != D3D_SRV_DIMENSION_UNKNOWN || IsVerbose) + Json.StringField("Dimension", DimensionTypeToString(reg.GetDimension())); + + if (reg.GetReturnType() || IsVerbose) + Json.StringField("ReturnType", ReturnTypeToString(reg.GetReturnType())); + + if (reg.GetBindCount() > 1 || IsVerbose) + Json.UIntField("BindCount", reg.GetBindCount()); + + if (reg.GetArrayId() != uint32_t(-1) || IsVerbose) { + + if (IsVerbose || AllRelevantMembers) + Json.UIntField("ArrayId", reg.GetArrayId()); + + Json.Array("ArraySize", [&Reflection, ®, &Json]() { + + if (reg.GetArrayId() == uint32_t(-1)) + return; + + const DxcHLSLArray &arr = Reflection.Arrays[reg.GetArrayId()]; + + for (uint32_t i = 0; i < uint32_t(arr.ArrayElem()); ++i) + Json.Value(uint64_t(Reflection.ArraySizes[arr.ArrayStart() + i])); + }); + } + + bool isBuffer = true; + + switch (reg.GetType()) { + case D3D_SIT_TEXTURE: + case D3D_SIT_SAMPLER: + case D3D_SIT_UAV_RWTYPED: + case D3D_SIT_RTACCELERATIONSTRUCTURE: + case D3D_SIT_UAV_FEEDBACKTEXTURE: + isBuffer = false; + break; + } + + if (isBuffer || IsVerbose) + Json.UIntField("BufferId", reg.GetBufferId()); + + if (reg.GetFlags() || IsVerbose) { + + Json.Array("Flags", [®, &Json]() { + + uint32_t flag = reg.GetFlags(); + + if (flag & D3D_SIF_USERPACKED) + Json.Value("UserPacked"); + + if (flag & D3D_SIF_COMPARISON_SAMPLER) + Json.Value("ComparisonSampler"); + + if (flag & D3D_SIF_TEXTURE_COMPONENT_0) + Json.Value("TextureComponent0"); + + if (flag & D3D_SIF_TEXTURE_COMPONENT_1) + Json.Value("TextureComponent1"); + + if (flag & D3D_SIF_UNUSED) + Json.Value("Unused"); + }); + } +} + +static void PrintTypeName(const DxcHLSLReflectionData &Reflection, uint32_t TypeId, + bool HasSymbols, bool IsVerbose, + bool AllRelevantMembers, JsonWriter &Json, + const char *NameForTypeName = "Name") { + + if (AllRelevantMembers || IsVerbose || !HasSymbols) + Json.UIntField("TypeId", TypeId); + + std::string name; + std::vector arraySizes; + + std::string underlyingName; + std::vector underlyingArraySizes; + + const DxcHLSLType &type = Reflection.Types[TypeId]; + + if (!HasSymbols) { + name = GetBuiltinTypeName(Reflection, type); + FillArraySizes(Reflection, type.GetUnderlyingArray(), arraySizes); + } + + else { + const DxcHLSLTypeSymbol &symbol = Reflection.TypeSymbols[TypeId]; + name = Reflection.Strings[symbol.DisplayNameId]; + FillArraySizes(Reflection, symbol.DisplayArray, arraySizes); + underlyingName = Reflection.Strings[symbol.UnderlyingNameId]; + FillArraySizes(Reflection, type.GetUnderlyingArray(), underlyingArraySizes); + } + + if (name.size() || IsVerbose) + Json.StringField(NameForTypeName, name); + + if (arraySizes.size() || IsVerbose) + Json.Array("ArraySize", [&arraySizes, &Json]() { + for (uint32_t i : arraySizes) + Json.Value(uint64_t(i)); + }); + + if ((underlyingName.size() && underlyingName != name) || IsVerbose) + Json.StringField("UnderlyingName", underlyingName); + + if ((underlyingArraySizes.size() && underlyingArraySizes != arraySizes) || IsVerbose) + Json.Array("UnderlyingArraySize", [&underlyingArraySizes, &Json]() { + for (uint32_t i : underlyingArraySizes) + Json.Value(uint64_t(i)); + }); +} + +static void PrintType(const DxcHLSLReflectionData &Reflection, uint32_t TypeId, + bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, + JsonWriter &Json) { + + const DxcHLSLType &type = Reflection.Types[TypeId]; + + JsonWriter::ObjectScope nodeRoot(Json); + PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, + Json); + + if (type.GetBaseClass() != uint32_t(-1)) + Json.Object("BaseClass", [&Reflection, &Json, &type, HasSymbols, IsVerbose, + AllRelevantMembers]() { + PrintTypeName(Reflection, type.GetBaseClass(), HasSymbols, IsVerbose, + AllRelevantMembers, Json); + }); + + else if (IsVerbose) + Json.NullField("BaseClass"); + + if (type.GetInterfaceCount()) + Json.Array("Interfaces", [&Reflection, &Json, &type, HasSymbols, IsVerbose, + AllRelevantMembers]() { + for (uint32_t i = 0; i < uint32_t(type.GetInterfaceCount()); ++i) { + uint32_t interfaceId = type.GetInterfaceStart() + i; + JsonWriter::ObjectScope nodeRoot(Json); + PrintTypeName(Reflection, Reflection.TypeList[interfaceId], HasSymbols, + IsVerbose, AllRelevantMembers, Json); + } + }); + + else if (IsVerbose) + Json.NullField("Interfaces"); + + if (type.GetMemberCount()) + Json.Array("Members", [&Reflection, &Json, &type, HasSymbols, IsVerbose, + AllRelevantMembers]() { + for (uint32_t i = 0; i < uint32_t(type.GetMemberCount()); ++i) { + + uint32_t memberId = type.GetMemberStart() + i; + JsonWriter::ObjectScope nodeRoot(Json); + + if (HasSymbols) { + Json.StringField( + "Name", Reflection.Strings[Reflection.MemberNameIds[memberId]]); + Json.UIntField("NameId", Reflection.MemberNameIds[memberId]); + } + + PrintTypeName(Reflection, Reflection.MemberTypeIds[memberId], + HasSymbols, IsVerbose, AllRelevantMembers, Json, + "TypeName"); + } + }); + + else if (IsVerbose) + Json.NullField("Members"); +} + +static void PrintParameter(const DxcHLSLReflectionData &Reflection, uint32_t TypeId, + bool HasSymbols, bool IsVerbose, JsonWriter &Json, + uint32_t SemanticId, uint8_t InterpolationMode, + uint8_t Flags, bool AllRelevantMembers) { + + PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, Json, "TypeName"); + + if (SemanticId != uint32_t(-1) || IsVerbose) + Json.StringField("Semantic", SemanticId == uint32_t(-1) + ? "" + : Reflection.StringsNonDebug[SemanticId]); + + if (IsVerbose || (AllRelevantMembers && SemanticId != uint32_t(-1))) + Json.IntField("SemanticId", + SemanticId == uint32_t(-1) ? -1 : int64_t(SemanticId)); + + if ((Flags & (D3D_PF_IN | D3D_PF_OUT)) == (D3D_PF_IN | D3D_PF_OUT)) + Json.StringField("Access", "inout"); + + else if (Flags & D3D_PF_IN) + Json.StringField("Access", "in"); + + else if (Flags & D3D_PF_OUT) + Json.StringField("Access", "out"); + + else if (IsVerbose) + Json.StringField("Access", "in"); + + static const char *interpolationModes[] = {"Undefined", + "Constant", + "Linear", + "LinearCentroid", + "LinearNoperspective", + "LinearNoperspectiveCentroid", + "LinearSample", + "LinearNoperspectiveSample"}; + + if (InterpolationMode || IsVerbose) + Json.StringField("Interpolation", interpolationModes[InterpolationMode]); +} + +static void PrintFunction(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, + uint32_t FunctionId, bool IsVerbose, + bool AllRelevantMembers) { + + const DxcHLSLFunction &func = Reflection.Functions[FunctionId]; + + JsonWriter::ObjectScope nodeRoot(Json); + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (AllRelevantMembers || IsVerbose || !hasSymbols) { + Json.UIntField("FunctionId", FunctionId); + Json.UIntField("NodeId", func.GetNodeId()); + } + + if (hasSymbols) + Json.StringField( + "Name", + Reflection + .Strings[Reflection.NodeSymbols[func.GetNodeId()].GetNameId()]); + + else if (IsVerbose) + Json.StringField("Name", ""); + + Json.BoolField("HasDefinition", func.HasDefinition()); + + if (IsVerbose) { + Json.UIntField("NumParameters", func.GetNumParameters()); + Json.BoolField("HasReturn", func.HasReturn()); + } + + Json.Object("Params", [&Reflection, &func, &Json, hasSymbols, IsVerbose, + AllRelevantMembers]() { + for (uint32_t i = 0; i < uint32_t(func.GetNumParameters()); ++i) { + + uint32_t nodeId = func.GetNodeId() + 1 + i; + const DxcHLSLNode &node = Reflection.Nodes[nodeId]; + uint32_t localId = node.GetLocalId(); + + const DxcHLSLParameter ¶m = Reflection.Parameters[localId]; + std::string paramName = + hasSymbols + ? Reflection.Strings[Reflection.NodeSymbols[nodeId].GetNameId()] + : std::to_string(i); + + Json.Object(paramName.c_str(), [&Reflection, &func, &Json, hasSymbols, + IsVerbose, ¶m, &node, + AllRelevantMembers]() { + PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, Json, + node.GetSemanticId(), param.InterpolationMode, + param.Flags, AllRelevantMembers); + }); + } + }); + + if (!func.HasReturn()) + Json.StringField("ReturnType", "void"); + + else { + + const DxcHLSLNode &node = + Reflection.Nodes[func.GetNodeId() + 1 + func.GetNumParameters()]; + const DxcHLSLParameter ¶m = Reflection.Parameters[node.GetLocalId()]; + + Json.Object("ReturnType", [&Reflection, &func, &Json, hasSymbols, IsVerbose, + ¶m, &node, AllRelevantMembers]() { + PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, Json, + node.GetSemanticId(), param.InterpolationMode, param.Flags, + AllRelevantMembers); + }); + } +} + +static void PrintEnumValue(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, + uint32_t ChildId, bool IsVerbose, + bool AllRelevantMembers) { + + const DxcHLSLNode &child = Reflection.Nodes[ChildId]; + + const DxcHLSLEnumValue &val = Reflection.EnumValues[child.GetLocalId()]; + + const DxcHLSLNode &parent = Reflection.Nodes[child.GetParentId()]; + const DxcHLSLEnumDesc &enm = Reflection.Enums[parent.GetLocalId()]; + + switch (enm.Type) { + case D3D12_HLSL_ENUM_TYPE_INT: + case D3D12_HLSL_ENUM_TYPE_INT64_T: + case D3D12_HLSL_ENUM_TYPE_INT16_T: + Json.IntField("Value", val.Value); + break; + + default: + Json.UIntField("Value", uint64_t(val.Value)); + } + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (hasSymbols || IsVerbose) + Json.StringField( + "Name", + !hasSymbols + ? "" + : Reflection.Strings[Reflection.NodeSymbols[ChildId].GetNameId()]); +} + +static void PrintEnum(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, + uint32_t EnumId, bool IsVerbose, + bool AllRelevantMembers) { + + JsonWriter::ObjectScope nodeRoot(Json); + const DxcHLSLEnumDesc &enm = Reflection.Enums[EnumId]; + const DxcHLSLNode &node = Reflection.Nodes[enm.NodeId]; + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (AllRelevantMembers || IsVerbose || !hasSymbols) { + Json.UIntField("EnumId", EnumId); + Json.UIntField("NodeId", enm.NodeId); + } + + if (hasSymbols) + Json.StringField( + "Name", + Reflection.Strings[Reflection.NodeSymbols[enm.NodeId].GetNameId()]); + + else if (IsVerbose) + Json.StringField("Name", ""); + + Json.StringField("EnumType", EnumTypeToString(enm.Type)); + + Json.Array("Values", [&Json, &node, &enm, hasSymbols, &Reflection, IsVerbose, + AllRelevantMembers]() { + for (uint32_t i = 0; i < node.GetChildCount(); ++i) { + + uint32_t childId = enm.NodeId + 1 + i; + + JsonWriter::ObjectScope valueRoot(Json); + + if (!hasSymbols || AllRelevantMembers || IsVerbose) + Json.UIntField("ValueId", i); + + PrintEnumValue(Json, Reflection, childId, IsVerbose, AllRelevantMembers); + } + }); +} + +static void PrintAnnotation(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, + const DxcHLSLAnnotation &Annot) { + Json.StringField("Contents", + Reflection.StringsNonDebug[Annot.GetStringNonDebug()]); + Json.StringField("Type", Annot.GetIsBuiltin() ? "Builtin" : "User"); +} + +static void PrintBufferMemberMember(const DxcHLSLReflectionData &Reflection, + bool HasSymbols, bool IsVerbose, + bool AllRelevantMembers, JsonWriter &Json, + uint32_t ChildId, uint32_t MemberId) { + + uint32_t TypeId = Reflection.MemberTypeIds[MemberId]; + + JsonWriter::ObjectScope nodeRoot(Json); + + if (IsVerbose || AllRelevantMembers || !HasSymbols) + Json.UIntField("ChildId", ChildId); + + if (HasSymbols) + Json.StringField("Name", + Reflection.Strings[Reflection.MemberNameIds[MemberId]]); + + else if (IsVerbose) + Json.StringField("Name", ""); + + const DxcHLSLType &type = Reflection.Types[TypeId]; + + PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, + Json, "TypeName"); + + if (type.GetMemberCount()) + Json.Array("Children", [&type, &Reflection, &Json, HasSymbols, IsVerbose, + AllRelevantMembers]() { + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { + + uint32_t memberId = type.GetMemberStart() + i; + + PrintBufferMemberMember(Reflection, HasSymbols, IsVerbose, + AllRelevantMembers, Json, i, memberId); + } + }); +} + +static uint32_t PrintBufferMember(const DxcHLSLReflectionData &Reflection, + uint32_t NodeId, uint32_t ChildId, bool HasSymbols, + bool IsVerbose, bool AllRelevantMembers, + JsonWriter &Json) { + + const DxcHLSLNode &node = Reflection.Nodes[NodeId]; + + JsonWriter::ObjectScope root(Json); + + if (IsVerbose || AllRelevantMembers) + Json.UIntField("NodeId", NodeId); + + if (!HasSymbols || AllRelevantMembers || IsVerbose) + Json.UIntField("ChildId", ChildId); + + if (HasSymbols) + Json.StringField( + "Name", Reflection.Strings[Reflection.NodeSymbols[NodeId].GetNameId()]); + + else if (IsVerbose) + Json.StringField("Name", ""); + + PrintTypeName(Reflection, node.GetLocalId(), HasSymbols, IsVerbose, + AllRelevantMembers, Json, "TypeName"); + + const DxcHLSLType &type = Reflection.Types[node.GetLocalId()]; + + if (type.GetMemberCount() || IsVerbose) + Json.Array("Children", [&type, &Reflection, &Json, HasSymbols, IsVerbose, + AllRelevantMembers]() { + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) + PrintBufferMemberMember(Reflection, HasSymbols, IsVerbose, + AllRelevantMembers, Json, i, + type.GetMemberStart() + i); + }); + + return node.GetChildCount(); +} + +static void PrintBuffer(const DxcHLSLReflectionData &Reflection, uint32_t BufferId, + bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, + JsonWriter &Json) { + + JsonWriter::ObjectScope nodeRoot(Json); + const DxcHLSLBuffer &buf = Reflection.Buffers[BufferId]; + const DxcHLSLNode &node = Reflection.Nodes[buf.NodeId]; + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + if (AllRelevantMembers || IsVerbose || !hasSymbols) { + Json.UIntField("BufferId", BufferId); + Json.UIntField("NodeId", buf.NodeId); + } + + if (hasSymbols) + Json.StringField( + "Name", + Reflection.Strings[Reflection.NodeSymbols[buf.NodeId].GetNameId()]); + + else if (IsVerbose) + Json.StringField("Name", ""); + + Json.StringField("Type", BufferTypeToString(buf.Type)); + + if (node.GetChildCount() || IsVerbose) + Json.Array("Children", [&node, &Reflection, &buf, &Json, HasSymbols, + IsVerbose, AllRelevantMembers]() { + for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) + i += PrintBufferMember(Reflection, buf.NodeId + 1 + i, j, HasSymbols, + IsVerbose, AllRelevantMembers, Json); + }); +} + +static void PrintStatement(const DxcHLSLReflectionData &Reflection, + const DxcHLSLStatement &Stmt, JsonWriter &Json, + bool IsVerbose) { + + const DxcHLSLNode &node = Reflection.Nodes[Stmt.GetNodeId()]; + + uint32_t nodesA = Stmt.GetNodeCount(); + uint32_t nodesB = node.GetChildCount() - nodesA - Stmt.HasConditionVar(); + + Json.BoolField("HasConditionVar", Stmt.HasConditionVar()); + + bool isIf = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF; + + if (isIf || IsVerbose) + Json.BoolField("HasElse", Stmt.HasElse()); + + if (nodesA || IsVerbose) + Json.UIntField("NodesA", nodesA); + + if (nodesB || IsVerbose) + Json.UIntField("NodesB", nodesB); +} + +//IsHumanFriendly = false: Raw view of the real file data +//IsHumanFriendly = true: Clean view that's relatively close to the real tree +std::string DxcHLSLReflectionData::ToJson( + bool IsHumanFriendly, bool IsVerbose) const { + + JsonWriter json; + + { + JsonWriter::ObjectScope root(json); + + // Features + + PrintFeatures(Features, json); + + bool hasSymbols = + Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + // Print raw contents + + if (!IsHumanFriendly) { + + json.Array("Strings", [this, &json] { + for (const std::string &s : Strings) + json.Value(s); + }); + + json.Array("StringsNonDebug", [this, &json] { + for (const std::string &s : StringsNonDebug) + json.Value(s); + }); + + json.Array("Sources", [this, &json] { + for (uint32_t id : Sources) + json.Value(Strings[id]); + }); + + json.Array("SourcesAsId", [this, &json] { + for (uint32_t id : Sources) + json.Value(uint64_t(id)); + }); + + json.Array("Nodes", [this, &json, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Nodes.size()); ++i) + PrintNode(json, *this, i, IsVerbose, true); + }); + + json.Array("Registers", [this, &json, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Registers.size()); ++i) + PrintRegister(json, *this, i, IsVerbose, true); + }); + + json.Array("Functions", [this, &json, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Functions.size()); ++i) + PrintFunction(json, *this, i, IsVerbose, true); + }); + + // Already referenced indirectly through other properties we printed + // before, still printing it to allow consistency checks. + // For pure pretty prints, you should use the human version. + + json.Array("Parameters", [this, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Parameters.size()); ++i) { + JsonWriter::ObjectScope nodeRoot(json); + + const DxcHLSLParameter ¶m = Parameters[i]; + std::string paramName = + hasSymbols ? Strings[NodeSymbols[param.NodeId].GetNameId()] + : std::to_string(i); + + json.StringField("ParamName", paramName); + + PrintParameter(*this, param.TypeId, hasSymbols, IsVerbose, json, + Nodes[param.NodeId].GetSemanticId(), + param.InterpolationMode, param.Flags, true); + } + }); + + json.Array("Enums", [this, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Enums.size()); ++i) + PrintEnum(json, *this, i, IsVerbose, true); + }); + + json.Array("EnumValues", [this, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(EnumValues.size()); ++i) { + JsonWriter::ObjectScope valueRoot(json); + PrintEnumValue(json, *this, EnumValues[i].NodeId, + IsVerbose, true); + } + }); + + json.Array("Annotations", [this, &json, hasSymbols] { + for (uint32_t i = 0; i < uint32_t(Annotations.size()); ++i) { + const DxcHLSLAnnotation &annot = Annotations[i]; + JsonWriter::ObjectScope valueRoot(json); + json.UIntField("StringId", annot.GetStringNonDebug()); + PrintAnnotation(json, *this, annot); + } + }); + + json.Array("Arrays", [this, &json] { + for (uint32_t i = 0; i < uint32_t(Arrays.size()); ++i) { + const DxcHLSLArray &arr = Arrays[i]; + JsonWriter::ObjectScope valueRoot(json); + json.UIntField("ArrayElem", arr.ArrayElem()); + json.UIntField("ArrayStart", arr.ArrayStart()); + json.Array("ArraySizes", [this, &json, &arr] { + for (uint32_t i = 0; i < arr.ArrayElem(); ++i) { + json.Value(uint64_t(ArraySizes[arr.ArrayStart() + i])); + } + }); + } + }); + + json.Array("ArraySizes", [this, &json] { + for (uint32_t id : ArraySizes) + json.Value(uint64_t(id)); + }); + + json.Array("Members", [this, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(MemberTypeIds.size()); ++i) { + + JsonWriter::ObjectScope valueRoot(json); + + if (hasSymbols) { + json.StringField("Name", Strings[MemberNameIds[i]]); + json.UIntField("NameId", MemberNameIds[i]); + } + + PrintTypeName(*this, MemberTypeIds[i], hasSymbols, IsVerbose, true, + json, "TypeName"); + } + }); + + json.Array("TypeList", [this, &json, hasSymbols, IsVerbose] { + for (uint32_t id : TypeList) { + JsonWriter::ObjectScope valueRoot(json); + PrintTypeName(*this, id, hasSymbols, IsVerbose, true, json); + } + }); + + json.Array("Types", [this, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Types.size()); ++i) + PrintType(*this, i, hasSymbols, IsVerbose, true, json); + }); + + json.Array("Buffers", [this, &json, hasSymbols, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Buffers.size()); ++i) + PrintBuffer(*this, i, hasSymbols, IsVerbose, true, json); + }); + + json.Array("Statements", [this, &json, IsVerbose] { + for (uint32_t i = 0; i < uint32_t(Statements.size()); ++i) { + + const DxcHLSLStatement &stat = Statements[i]; + JsonWriter::ObjectScope valueRoot(json); + json.StringField( + "Type", NodeTypeToString( + Nodes[stat.GetNodeId()].GetNodeType())); + json.UIntField("NodeId", stat.GetNodeId()); + + PrintStatement(*this, stat, json, IsVerbose); + } + }); + } + + else { + // TODO: Print pretty tree for user + } + } + + return json.str(); +} + +} // namespace hlsl diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index 3ae5f7d050..cbb4e1cb2e 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -45,8 +45,6 @@ #include "dxc/DxcReflection/DxcReflection.h" -#include - using namespace llvm; using namespace clang; using namespace hlsl; @@ -1549,1280 +1547,6 @@ HRESULT GenerateAST(DxcLangExtensionsHelper *pExtHelper, LPCSTR pFileName, return S_OK; } -//TODO: Print escape character - -struct JsonWriter { - - std::stringstream ss; - uint16_t indent = 0; - uint16_t countCommaStack = 0; - uint32_t needCommaStack = 0; - - void Indent() { ss << std::string(indent, '\t'); } - void NewLine() { ss << "\n"; } - - void StartCommaStack() { - ++countCommaStack; - assert(countCommaStack < 32 && "countCommaStack out of bounds"); - needCommaStack &= ~(1u << countCommaStack); - } - - void SetComma() { needCommaStack |= 1u << countCommaStack; } - - void EndCommaStack() { - --countCommaStack; - SetComma(); - } - - bool NeedsComma() { return (needCommaStack >> countCommaStack) & 1; } - - void BeginObj() { - - if (NeedsComma()) { - ss << ",\n"; - Indent(); - } - - ss << "{\n"; - ++indent; - StartCommaStack(); - Indent(); - } - - void EndObj() { - ss << "\n"; - --indent; - Indent(); - ss << "}"; - EndCommaStack(); - } - - void BeginArray(const char *Name) { - - if (NeedsComma()) { - ss << ",\n"; - Indent(); - } - - if (Name) { - StartCommaStack(); - Key(Name); - --countCommaStack; - } - - ss << "[\n"; - ++indent; - StartCommaStack(); - Indent(); - } - - void EndArray() { - ss << "\n"; - --indent; - Indent(); - ss << "]"; - EndCommaStack(); - } - - void Key(const char *Key) { - if (NeedsComma()) { - ss << ",\n"; - Indent(); - } - ss << "\"" << Escape(Key) << "\": "; - } - - void Value(std::string S) { - if (NeedsComma()) { - ss << ",\n"; - Indent(); - } - ss << "\"" << Escape(S) << "\""; - SetComma(); - } - - void Value(const char *S) { - if (NeedsComma()) { - ss << ",\n"; - Indent(); - } - ss << "\"" << S << "\""; - SetComma(); - } - - void ValueNull() { - if (NeedsComma()) { - ss << ",\n"; - Indent(); - } - ss << "null"; - SetComma(); - } - - void Value(uint64_t V) { - if (NeedsComma()) { - ss << ",\n"; - Indent(); - } - ss << V; - SetComma(); - } - - void Value(int64_t V) { - if (NeedsComma()) { - ss << ",\n"; - Indent(); - } - ss << V; - SetComma(); - } - - void Value(bool V) { - if (NeedsComma()) { - ss << ",\n"; - Indent(); - } - ss << (V ? "true" : "false"); - SetComma(); - } - - static std::string Escape(const std::string &In) { - std::string out; - out.reserve(In.size()); - for (char c : In) { - switch (c) { - case '\\': - out += "\\\\"; - break; - case '"': - out += "\\\""; - break; - case '\n': - out += "\\n"; - break; - case '\r': - out += "\\r"; - break; - case '\t': - out += "\\t"; - break; - default: - out += c; - break; - } - } - return out; - } - - std::string str() const { return ss.str(); } - - struct ObjectScope { - - JsonWriter &W; - bool NeedsEndCommaStack; - - ObjectScope(JsonWriter &W, const char *Name = nullptr) - : W(W), NeedsEndCommaStack(Name) { - - if (Name) { - W.Key(Name); - W.StartCommaStack(); - } - - W.BeginObj(); - } - - ~ObjectScope() { - W.EndObj(); - - if (NeedsEndCommaStack) - W.EndCommaStack(); - } - }; - - struct ArrayScope { - JsonWriter &W; - ArrayScope(JsonWriter &W, const char *Name = nullptr) : W(W) { - W.BeginArray(Name); - } - ~ArrayScope() { W.EndArray(); } - }; - - void Object(const char *Name, const std::function &Body) { - ObjectScope _(*this, Name); - Body(); - } - - void Array(const char *Name, const std::function &Body) { - ArrayScope _( *this, Name ); Body(); - } - - void StringField(const char *K, const std::string &V) { - Key(K); - StartCommaStack(); - Value(V); - EndCommaStack(); - } - - void UIntField(const char *K, uint64_t V) { - Key(K); - StartCommaStack(); - Value(V); - EndCommaStack(); - } - - void IntField(const char *K, int64_t V) { - Key(K); - StartCommaStack(); - Value(V); - EndCommaStack(); - } - - void BoolField(const char *K, bool V) { - Key(K); - StartCommaStack(); - Value(V); - EndCommaStack(); - } - - void NullField(const char *K) { - Key(K); - StartCommaStack(); - ValueNull(); - EndCommaStack(); - } -}; - -void PrintFeatures(D3D12_HLSL_REFLECTION_FEATURE Features, JsonWriter &Json) { - Json.Array("Features", [Features, &Json] { - if (Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS) - Json.Value("Basics"); - if (Features & D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS) - Json.Value("Functions"); - if (Features & D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES) - Json.Value("Namespaces"); - if (Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES) - Json.Value("UserTypes"); - if (Features & D3D12_HLSL_REFLECTION_FEATURE_SCOPES) - Json.Value("Scopes"); - if (Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) - Json.Value("Symbols"); - }); -} - -static const char *NodeTypeToString(D3D12_HLSL_NODE_TYPE Type) { - - static const char *arr[] = {"Register", - "Function", - "Enum", - "EnumValue", - "Namespace", - "Variable", - "Typedef", - "Struct", - "Union", - "StaticVariable", - "Interface", - "Parameter", - "If", - "Scope", - "Do", - "Switch", - "While", - "For", - "GroupsharedVariable"}; - - return arr[uint32_t(Type)]; -} - -static const char *RegisterTypeToString(D3D_SHADER_INPUT_TYPE Type) { - - static const char *arr[] = {"cbuffer", - "tbuffer", - "Texture", - "SamplerState", - "RWTexture", - "StructuredBuffer", - "RWStructuredBuffer", - "ByteAddressBuffer", - "RWByteAddressBuffer", - "AppendStructuredBuffer", - "ConsumeStructuredBuffer", - "(Append/Consume)StructuredBuffer", - "RaytracingAccelerationStructure", - "FeedbackTexture"}; - - return arr[uint32_t(Type)]; -} - -static const char *DimensionTypeToString(D3D_SRV_DIMENSION Type) { - - static const char *arr[] = { - "Unknown", "Buffer", "Texture1D", "Texture1DArray", - "Texture2D", "Texture2DArray", "Texture2DMS", "Texture2DMSArray", - "Texture3D", "TextureCube", "TextureCubeArray", "BufferEx"}; - - return arr[uint32_t(Type)]; -} - -static const char *ReturnTypeToString(D3D_RESOURCE_RETURN_TYPE Type) { - - static const char *arr[] = {"unknown", "unorm", "snorm", "sint", "uint", - "float", "mixed", "double", "continued"}; - - return arr[uint32_t(Type)]; -} - -static std::string EnumTypeToString(D3D12_HLSL_ENUM_TYPE Type) { - - static const char *arr[] = { - "uint", "int", "uint64_t", "int64_t", "uint16_t", "int16_t", - }; - - return arr[Type]; -} - -static std::string BufferTypeToString(D3D_CBUFFER_TYPE Type) { - static const char *arr[] = {"cbuffer", "tbuffer", "undefined", "structured"}; - return arr[Type]; -} - -static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, - const DxcHLSLType &Type) { - - std::string type = ""; - - if (Type.GetClass() != D3D_SVC_STRUCT && Type.GetClass() != D3D_SVC_INTERFACE_CLASS) { - - static const char *arr[] = {"void", - "bool", - "int", - "float", - "string", - NULL, - "Texture1D", - "Texture2D", - "Texture3D", - "TextureCube", - "SamplerState", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "uint", - "uint8_t", - NULL, - NULL, - NULL, - NULL, - "Buffer", - "ConstantBuffer", - NULL, - "Texture1DArray", - "Texture2DArray", - NULL, - NULL, - "Texture2DMS", - "Texture2DMSArray", - "TextureCubeArray", - NULL, - NULL, - NULL, - NULL, - "double", - "RWTexture1D", - "RWTexture1DArray", - "RWTexture2D", - "RWTexture2DArray", - "RWTexture3D", - "RWBuffer", - "ByteAddressBuffer", - "RWByteAddressBuffer", - "StructuredBuffer", - "RWStructuredBuffer", - "AppendStructuredBuffer", - "ConsumeStructuredBuffer", - "min8float", - "min10float", - "min16float", - "min12int", - "min16int", - "min16uint", - "int16_t", - "uint16_t", - "float16_t", - "int64_t", - "uint64_t"}; - - const char *ptr = arr[Type.GetType()]; - - if (ptr) - type = ptr; - } - - switch (Type.GetClass()) { - - case D3D_SVC_MATRIX_ROWS: - case D3D_SVC_VECTOR: - - type += std::to_string(Type.GetColumns()); - - if (Type.GetClass() == D3D_SVC_MATRIX_ROWS) - type += "x" + std::to_string(Type.GetRows()); - - break; - - case D3D_SVC_MATRIX_COLUMNS: - type += std::to_string(Type.GetRows()) + "x" + - std::to_string(Type.GetColumns()); - break; - } - - return type; -} - -static void FillArraySizes(DxcHLSLReflectionData &Reflection, - DxcHLSLArrayOrElements Elements, - std::vector &Array) { - - if (!Elements.IsArray()) - return; - - if (Elements.Is1DArray()) { - Array.push_back(Elements.Get1DElements()); - return; - } - - const DxcHLSLArray &arr = - Reflection.Arrays[Elements.GetMultiDimensionalArrayId()]; - - for (uint32_t i = 0; i < arr.ArrayElem(); ++i) - Array.push_back(Reflection.ArraySizes[arr.ArrayStart() + i]); -} - -//Verbose and all members are slightly different; -//Verbose will still print fields even if they aren't relevant, -// while all members will not silence important info but that might not matter for human readability -static void PrintNode(JsonWriter &Json, DxcHLSLReflectionData &Reflection, - uint32_t NodeId, bool IsVerbose, bool AllRelevantMembers) { - - DxcHLSLNode &node = Reflection.Nodes[NodeId]; - - JsonWriter::ObjectScope nodeRoot(Json); - - bool hasSymbols = - Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - if (AllRelevantMembers || IsVerbose || !hasSymbols) - Json.UIntField("NodeId", NodeId); - - Json.StringField("NodeType", NodeTypeToString(node.GetNodeType())); - - if (IsVerbose || AllRelevantMembers) { - Json.UIntField("NodeTypeId", node.GetNodeType()); - Json.UIntField("LocalId", node.GetLocalId()); - Json.IntField("ParentId", node.GetParentId() == uint16_t(-1) - ? -1 - : int64_t(node.GetParentId())); - } - - if (IsVerbose || (node.GetChildCount() && AllRelevantMembers)) { - Json.UIntField("ChildCount", node.GetChildCount()); - Json.UIntField("ChildStart", NodeId + 1); - } - - if (node.GetSemanticId() != uint32_t(-1) || IsVerbose) - Json.StringField("Semantic", - node.GetSemanticId() != uint32_t(-1) - ? Reflection.StringsNonDebug[node.GetSemanticId()] - : ""); - - if (IsVerbose || (AllRelevantMembers && node.GetSemanticId() != uint32_t(-1))) - Json.IntField("SemanticId", node.GetSemanticId() == uint32_t(-1) ? -1 : int64_t(node.GetSemanticId())); - - if (IsVerbose || (AllRelevantMembers && node.GetAnnotationCount())) { - Json.UIntField("AnnotationStart", node.GetAnnotationStart()); - Json.UIntField("AnnotationCount", node.GetAnnotationCount()); - } - - if (node.GetAnnotationCount() || IsVerbose) - Json.Array("Annotations", [&Reflection, &Json, node] { - for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) { - - const DxcHLSLAnnotation &annot = - Reflection.Annotations[node.GetAnnotationStart() + i]; - - std::string name = - Reflection.StringsNonDebug[annot.GetStringNonDebug()]; - - if (annot.GetIsBuiltin()) - name = "[" + name + "]"; - else - name = "[[" + name + "]]"; - - Json.Value(name); - } - }); - - if ((node.IsFwdBckDefined() || node.IsFwdDeclare()) || IsVerbose) { - - Json.BoolField("IsFwdDeclare", node.IsFwdDeclare()); - Json.BoolField("IsFwdBackDefined", node.IsFwdBckDefined()); - - if (node.IsFwdBckDefined() || IsVerbose) - Json.IntField("FwdBack", - !node.IsFwdBckDefined() ? -1 : int64_t(node.GetFwdBck())); - } - - if (hasSymbols) { - - Json.Object("Symbol", [&Reflection, &Json, NodeId, IsVerbose, - AllRelevantMembers] { - DxcHLSLNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; - Json.StringField("Name", Reflection.Strings[sym.GetNameId()]); - - if (IsVerbose || AllRelevantMembers) - Json.UIntField("NameId", sym.GetNameId()); - - if (sym.HasFileSource()) { - - Json.StringField( - "Source", - Reflection.Strings[Reflection.Sources[sym.GetFileSourceId()]]); - - if (IsVerbose || AllRelevantMembers) - Json.UIntField("SourceId", sym.GetFileSourceId()); - - Json.UIntField("LineId", sym.GetSourceLineStart()); - Json.UIntField("LineCount", sym.GetSourceLineCount()); - - Json.UIntField("ColumnStart", sym.GetSourceColumnStart()); - Json.UIntField("ColumnEnd", sym.GetSourceColumnEnd()); - - } else if (IsVerbose) { - - Json.StringField("Source", ""); - Json.IntField("SourceId", -1); - - Json.IntField("LineId", -1); - Json.UIntField("LineCount", 0); - - Json.IntField("ColumnStart", -1); - Json.UIntField("ColumnEnd", 0); - } - }); - - } else if (IsVerbose) - Json.NullField("Symbol"); -} - -static void PrintRegister(JsonWriter &Json, DxcHLSLReflectionData &Reflection, - uint32_t RegisterId, bool IsVerbose, - bool AllRelevantMembers) { - - DxcHLSLRegister ® = Reflection.Registers[RegisterId]; - - JsonWriter::ObjectScope nodeRoot(Json); - - bool hasSymbols = - Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - if (IsVerbose || AllRelevantMembers || !hasSymbols) { - Json.UIntField("RegisterId", RegisterId); - Json.UIntField("NodeId", reg.GetNodeId()); - } - - if (hasSymbols) - Json.StringField( - "Name", - Reflection - .Strings[Reflection.NodeSymbols[reg.GetNodeId()].GetNameId()]); - - else if (IsVerbose) - Json.StringField("Name", ""); - - Json.StringField("RegisterType", RegisterTypeToString(reg.GetType())); - - if (reg.GetDimension() != D3D_SRV_DIMENSION_UNKNOWN || IsVerbose) - Json.StringField("Dimension", DimensionTypeToString(reg.GetDimension())); - - if (reg.GetReturnType() || IsVerbose) - Json.StringField("ReturnType", ReturnTypeToString(reg.GetReturnType())); - - if (reg.GetBindCount() > 1 || IsVerbose) - Json.UIntField("BindCount", reg.GetBindCount()); - - if (reg.GetArrayId() != uint32_t(-1) || IsVerbose) { - - if (IsVerbose || AllRelevantMembers) - Json.UIntField("ArrayId", reg.GetArrayId()); - - Json.Array("ArraySize", [&Reflection, ®, &Json]() { - - if (reg.GetArrayId() == uint32_t(-1)) - return; - - const DxcHLSLArray &arr = Reflection.Arrays[reg.GetArrayId()]; - - for (uint32_t i = 0; i < uint32_t(arr.ArrayElem()); ++i) - Json.Value(uint64_t(Reflection.ArraySizes[arr.ArrayStart() + i])); - }); - } - - bool isBuffer = true; - - switch (reg.GetType()) { - case D3D_SIT_TEXTURE: - case D3D_SIT_SAMPLER: - case D3D_SIT_UAV_RWTYPED: - case D3D_SIT_RTACCELERATIONSTRUCTURE: - case D3D_SIT_UAV_FEEDBACKTEXTURE: - isBuffer = false; - break; - } - - if (isBuffer || IsVerbose) - Json.UIntField("BufferId", reg.GetBufferId()); - - if (reg.GetFlags() || IsVerbose) { - - Json.Array("Flags", [®, &Json]() { - - uint32_t flag = reg.GetFlags(); - - if (flag & D3D_SIF_USERPACKED) - Json.Value("UserPacked"); - - if (flag & D3D_SIF_COMPARISON_SAMPLER) - Json.Value("ComparisonSampler"); - - if (flag & D3D_SIF_TEXTURE_COMPONENT_0) - Json.Value("TextureComponent0"); - - if (flag & D3D_SIF_TEXTURE_COMPONENT_1) - Json.Value("TextureComponent1"); - - if (flag & D3D_SIF_UNUSED) - Json.Value("Unused"); - }); - } -} - -static void PrintTypeName(DxcHLSLReflectionData &Reflection, uint32_t TypeId, - bool HasSymbols, bool IsVerbose, - bool AllRelevantMembers, JsonWriter &Json, - const char *NameForTypeName = "Name") { - - if (AllRelevantMembers || IsVerbose || !HasSymbols) - Json.UIntField("TypeId", TypeId); - - std::string name; - std::vector arraySizes; - - std::string underlyingName; - std::vector underlyingArraySizes; - - const DxcHLSLType &type = Reflection.Types[TypeId]; - - if (!HasSymbols) { - name = GetBuiltinTypeName(Reflection, type); - FillArraySizes(Reflection, type.GetUnderlyingArray(), arraySizes); - } - - else { - const DxcHLSLTypeSymbol &symbol = Reflection.TypeSymbols[TypeId]; - name = Reflection.Strings[symbol.DisplayNameId]; - FillArraySizes(Reflection, symbol.DisplayArray, arraySizes); - underlyingName = Reflection.Strings[symbol.UnderlyingNameId]; - FillArraySizes(Reflection, type.GetUnderlyingArray(), underlyingArraySizes); - } - - if (name.size() || IsVerbose) - Json.StringField(NameForTypeName, name); - - if (arraySizes.size() || IsVerbose) - Json.Array("ArraySize", [&arraySizes, &Json]() { - for (uint32_t i : arraySizes) - Json.Value(uint64_t(i)); - }); - - if ((underlyingName.size() && underlyingName != name) || IsVerbose) - Json.StringField("UnderlyingName", underlyingName); - - if ((underlyingArraySizes.size() && underlyingArraySizes != arraySizes) || IsVerbose) - Json.Array("UnderlyingArraySize", [&underlyingArraySizes, &Json]() { - for (uint32_t i : underlyingArraySizes) - Json.Value(uint64_t(i)); - }); -} - -static void PrintType(DxcHLSLReflectionData &Reflection, uint32_t TypeId, - bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, - JsonWriter &Json) { - - const DxcHLSLType &type = Reflection.Types[TypeId]; - - JsonWriter::ObjectScope nodeRoot(Json); - PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, - Json); - - if (type.GetBaseClass() != uint32_t(-1)) - Json.Object("BaseClass", [&Reflection, &Json, &type, HasSymbols, IsVerbose, - AllRelevantMembers]() { - PrintTypeName(Reflection, type.GetBaseClass(), HasSymbols, IsVerbose, - AllRelevantMembers, Json); - }); - - else if (IsVerbose) - Json.NullField("BaseClass"); - - if (type.GetInterfaceCount()) - Json.Array("Interfaces", [&Reflection, &Json, &type, HasSymbols, IsVerbose, - AllRelevantMembers]() { - for (uint32_t i = 0; i < uint32_t(type.GetInterfaceCount()); ++i) { - uint32_t interfaceId = type.GetInterfaceStart() + i; - JsonWriter::ObjectScope nodeRoot(Json); - PrintTypeName(Reflection, Reflection.TypeList[interfaceId], HasSymbols, - IsVerbose, AllRelevantMembers, Json); - } - }); - - else if (IsVerbose) - Json.NullField("Interfaces"); - - if (type.GetMemberCount()) - Json.Array("Members", [&Reflection, &Json, &type, HasSymbols, IsVerbose, - AllRelevantMembers]() { - for (uint32_t i = 0; i < uint32_t(type.GetMemberCount()); ++i) { - - uint32_t memberId = type.GetMemberStart() + i; - JsonWriter::ObjectScope nodeRoot(Json); - - if (HasSymbols) { - Json.StringField( - "Name", Reflection.Strings[Reflection.MemberNameIds[memberId]]); - Json.UIntField("NameId", Reflection.MemberNameIds[memberId]); - } - - PrintTypeName(Reflection, Reflection.MemberTypeIds[memberId], - HasSymbols, IsVerbose, AllRelevantMembers, Json, - "TypeName"); - } - }); - - else if (IsVerbose) - Json.NullField("Members"); -} - -static void PrintParameter(DxcHLSLReflectionData &Reflection, uint32_t TypeId, - bool HasSymbols, bool IsVerbose, JsonWriter &Json, - uint32_t SemanticId, uint8_t InterpolationMode, - uint8_t Flags, bool AllRelevantMembers) { - - PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, Json, "TypeName"); - - if (SemanticId != uint32_t(-1) || IsVerbose) - Json.StringField("Semantic", SemanticId == uint32_t(-1) - ? "" - : Reflection.StringsNonDebug[SemanticId]); - - if (IsVerbose || (AllRelevantMembers && SemanticId != uint32_t(-1))) - Json.IntField("SemanticId", - SemanticId == uint32_t(-1) ? -1 : int64_t(SemanticId)); - - if ((Flags & (D3D_PF_IN | D3D_PF_OUT)) == (D3D_PF_IN | D3D_PF_OUT)) - Json.StringField("Access", "inout"); - - else if (Flags & D3D_PF_IN) - Json.StringField("Access", "in"); - - else if (Flags & D3D_PF_OUT) - Json.StringField("Access", "out"); - - else if (IsVerbose) - Json.StringField("Access", "in"); - - static const char *interpolationModes[] = {"Undefined", - "Constant", - "Linear", - "LinearCentroid", - "LinearNoperspective", - "LinearNoperspectiveCentroid", - "LinearSample", - "LinearNoperspectiveSample"}; - - if (InterpolationMode || IsVerbose) - Json.StringField("Interpolation", interpolationModes[InterpolationMode]); -} - -static void PrintFunction(JsonWriter &Json, DxcHLSLReflectionData &Reflection, - uint32_t FunctionId, bool IsVerbose, - bool AllRelevantMembers) { - - DxcHLSLFunction &func = Reflection.Functions[FunctionId]; - - JsonWriter::ObjectScope nodeRoot(Json); - - bool hasSymbols = - Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - if (AllRelevantMembers || IsVerbose || !hasSymbols) { - Json.UIntField("FunctionId", FunctionId); - Json.UIntField("NodeId", func.GetNodeId()); - } - - if (hasSymbols) - Json.StringField( - "Name", - Reflection - .Strings[Reflection.NodeSymbols[func.GetNodeId()].GetNameId()]); - - else if (IsVerbose) - Json.StringField("Name", ""); - - Json.BoolField("HasDefinition", func.HasDefinition()); - - if (IsVerbose) { - Json.UIntField("NumParameters", func.GetNumParameters()); - Json.BoolField("HasReturn", func.HasReturn()); - } - - Json.Object("Params", [&Reflection, &func, &Json, hasSymbols, IsVerbose, - AllRelevantMembers]() { - for (uint32_t i = 0; i < uint32_t(func.GetNumParameters()); ++i) { - - uint32_t nodeId = func.GetNodeId() + 1 + i; - const DxcHLSLNode &node = Reflection.Nodes[nodeId]; - uint32_t localId = node.GetLocalId(); - - const DxcHLSLParameter ¶m = Reflection.Parameters[localId]; - std::string paramName = - hasSymbols - ? Reflection.Strings[Reflection.NodeSymbols[nodeId].GetNameId()] - : std::to_string(i); - - Json.Object(paramName.c_str(), [&Reflection, &func, &Json, hasSymbols, - IsVerbose, ¶m, &node, - AllRelevantMembers]() { - PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, Json, - node.GetSemanticId(), param.InterpolationMode, - param.Flags, AllRelevantMembers); - }); - } - }); - - if (!func.HasReturn()) - Json.StringField("ReturnType", "void"); - - else { - - const DxcHLSLNode &node = - Reflection.Nodes[func.GetNodeId() + 1 + func.GetNumParameters()]; - const DxcHLSLParameter ¶m = Reflection.Parameters[node.GetLocalId()]; - - Json.Object("ReturnType", [&Reflection, &func, &Json, hasSymbols, IsVerbose, - ¶m, &node, AllRelevantMembers]() { - PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, Json, - node.GetSemanticId(), param.InterpolationMode, param.Flags, - AllRelevantMembers); - }); - } -} - -static void PrintEnumValue(JsonWriter &Json, DxcHLSLReflectionData &Reflection, - uint32_t ChildId, bool IsVerbose, - bool AllRelevantMembers) { - - const DxcHLSLNode &child = Reflection.Nodes[ChildId]; - - const DxcHLSLEnumValue &val = Reflection.EnumValues[child.GetLocalId()]; - - const DxcHLSLNode &parent = Reflection.Nodes[child.GetParentId()]; - const DxcHLSLEnumDesc &enm = Reflection.Enums[parent.GetLocalId()]; - - switch (enm.Type) { - case D3D12_HLSL_ENUM_TYPE_INT: - case D3D12_HLSL_ENUM_TYPE_INT64_T: - case D3D12_HLSL_ENUM_TYPE_INT16_T: - Json.IntField("Value", val.Value); - break; - - default: - Json.UIntField("Value", uint64_t(val.Value)); - } - - bool hasSymbols = - Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - if (hasSymbols || IsVerbose) - Json.StringField( - "Name", - !hasSymbols - ? "" - : Reflection.Strings[Reflection.NodeSymbols[ChildId].GetNameId()]); -} - -static void PrintEnum(JsonWriter &Json, DxcHLSLReflectionData &Reflection, - uint32_t EnumId, bool IsVerbose, - bool AllRelevantMembers) { - - JsonWriter::ObjectScope nodeRoot(Json); - const DxcHLSLEnumDesc &enm = Reflection.Enums[EnumId]; - const DxcHLSLNode &node = Reflection.Nodes[enm.NodeId]; - - bool hasSymbols = - Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - if (AllRelevantMembers || IsVerbose || !hasSymbols) { - Json.UIntField("EnumId", EnumId); - Json.UIntField("NodeId", enm.NodeId); - } - - if (hasSymbols) - Json.StringField( - "Name", - Reflection.Strings[Reflection.NodeSymbols[enm.NodeId].GetNameId()]); - - else if (IsVerbose) - Json.StringField("Name", ""); - - Json.StringField("EnumType", EnumTypeToString(enm.Type)); - - Json.Array("Values", [&Json, &node, &enm, hasSymbols, &Reflection, IsVerbose, - AllRelevantMembers]() { - for (uint32_t i = 0; i < node.GetChildCount(); ++i) { - - uint32_t childId = enm.NodeId + 1 + i; - - JsonWriter::ObjectScope valueRoot(Json); - - if (!hasSymbols || AllRelevantMembers || IsVerbose) - Json.UIntField("ValueId", i); - - PrintEnumValue(Json, Reflection, childId, IsVerbose, AllRelevantMembers); - } - }); -} - -static void PrintAnnotation(JsonWriter &Json, DxcHLSLReflectionData &Reflection, - const DxcHLSLAnnotation &Annot) { - Json.StringField("Contents", - Reflection.StringsNonDebug[Annot.GetStringNonDebug()]); - Json.StringField("Type", Annot.GetIsBuiltin() ? "Builtin" : "User"); -} - -static void PrintBufferMemberMember(DxcHLSLReflectionData &Reflection, - bool HasSymbols, bool IsVerbose, - bool AllRelevantMembers, JsonWriter &Json, - uint32_t ChildId, uint32_t MemberId) { - - uint32_t TypeId = Reflection.MemberTypeIds[MemberId]; - - JsonWriter::ObjectScope nodeRoot(Json); - - if (IsVerbose || AllRelevantMembers || !HasSymbols) - Json.UIntField("ChildId", ChildId); - - if (HasSymbols) - Json.StringField("Name", - Reflection.Strings[Reflection.MemberNameIds[MemberId]]); - - else if (IsVerbose) - Json.StringField("Name", ""); - - const DxcHLSLType &type = Reflection.Types[TypeId]; - - PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, - Json, "TypeName"); - - if (type.GetMemberCount()) - Json.Array("Children", [&type, &Reflection, &Json, HasSymbols, IsVerbose, - AllRelevantMembers]() { - for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { - - uint32_t memberId = type.GetMemberStart() + i; - - PrintBufferMemberMember(Reflection, HasSymbols, IsVerbose, - AllRelevantMembers, Json, i, memberId); - } - }); -} - -static uint32_t PrintBufferMember(DxcHLSLReflectionData &Reflection, - uint32_t NodeId, bool HasSymbols, - bool IsVerbose, bool AllRelevantMembers, - JsonWriter &Json) { - - const DxcHLSLNode &node = Reflection.Nodes[NodeId]; - - JsonWriter::ObjectScope root(Json); - - if (IsVerbose || AllRelevantMembers || !HasSymbols) - Json.UIntField("NodeId", NodeId); - - if (HasSymbols) - Json.StringField( - "Name", Reflection.Strings[Reflection.NodeSymbols[NodeId].GetNameId()]); - - else if (IsVerbose) - Json.StringField("Name", ""); - - PrintTypeName(Reflection, node.GetLocalId(), HasSymbols, IsVerbose, - AllRelevantMembers, Json, "TypeName"); - - const DxcHLSLType &type = Reflection.Types[node.GetLocalId()]; - - if (type.GetMemberCount() || IsVerbose) - Json.Array("Children", [&type, &Reflection, &Json, HasSymbols, IsVerbose, - AllRelevantMembers]() { - for (uint32_t i = 0; i < type.GetMemberCount(); ++i) - PrintBufferMemberMember(Reflection, HasSymbols, IsVerbose, - AllRelevantMembers, Json, i, - type.GetMemberStart() + i); - }); - - return node.GetChildCount(); -} - -static void PrintBuffer(DxcHLSLReflectionData &Reflection, uint32_t BufferId, - bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, - JsonWriter &Json) { - - JsonWriter::ObjectScope nodeRoot(Json); - const DxcHLSLBuffer &buf = Reflection.Buffers[BufferId]; - const DxcHLSLNode &node = Reflection.Nodes[buf.NodeId]; - - bool hasSymbols = - Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - if (AllRelevantMembers || IsVerbose || !hasSymbols) { - Json.UIntField("BufferId", BufferId); - Json.UIntField("NodeId", buf.NodeId); - } - - if (hasSymbols) - Json.StringField( - "Name", - Reflection.Strings[Reflection.NodeSymbols[buf.NodeId].GetNameId()]); - - else if (IsVerbose) - Json.StringField("Name", ""); - - Json.StringField("Type", BufferTypeToString(buf.Type)); - - if (node.GetChildCount() || IsVerbose) - Json.Array("Children", [&node, &Reflection, &buf, &Json, HasSymbols, - IsVerbose, AllRelevantMembers]() { - for (uint32_t i = 0; i < node.GetChildCount(); ++i) - i += PrintBufferMember(Reflection, buf.NodeId + 1 + i, HasSymbols, - IsVerbose, AllRelevantMembers, Json); - }); -} - -static void PrintStatement(DxcHLSLReflectionData &Reflection, - const DxcHLSLStatement &Stmt, JsonWriter &Json, - bool IsVerbose) { - - const DxcHLSLNode &node = Reflection.Nodes[Stmt.GetNodeId()]; - - uint32_t nodesA = Stmt.GetNodeCount(); - uint32_t nodesB = node.GetChildCount() - nodesA - Stmt.HasConditionVar(); - - Json.BoolField("HasConditionVar", Stmt.HasConditionVar()); - - bool isIf = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF; - - if (isIf || IsVerbose) - Json.BoolField("HasElse", Stmt.HasElse()); - - if (nodesA || IsVerbose) - Json.UIntField("NodesA", nodesA); - - if (nodesB || IsVerbose) - Json.UIntField("NodesB", nodesB); -} - -//IsHumanFriendly = false: Raw view of the real file data -//IsHumanFriendly = true: Clean view that's relatively close to the real tree -static std::string ToJson(DxcHLSLReflectionData &Reflection, - bool IsHumanFriendly, bool IsVerbose) { - - JsonWriter json; - - { - JsonWriter::ObjectScope root(json); - - // Features - - PrintFeatures(Reflection.Features, json); - - bool hasSymbols = - Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - - // Print raw contents - - if (!IsHumanFriendly) { - - json.Array("Strings", [&Reflection, &json] { - for (const std::string &s : Reflection.Strings) - json.Value(s); - }); - - json.Array("StringsNonDebug", [&Reflection, &json] { - for (const std::string &s : Reflection.StringsNonDebug) - json.Value(s); - }); - - json.Array("Sources", [&Reflection, &json] { - for (uint32_t id : Reflection.Sources) - json.Value(Reflection.Strings[id]); - }); - - json.Array("SourcesAsId", [&Reflection, &json] { - for (uint32_t id : Reflection.Sources) - json.Value(uint64_t(id)); - }); - - json.Array("Nodes", [&Reflection, &json, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Reflection.Nodes.size()); ++i) - PrintNode(json, Reflection, i, IsVerbose, true); - }); - - json.Array("Registers", [&Reflection, &json, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Reflection.Registers.size()); ++i) - PrintRegister(json, Reflection, i, IsVerbose, true); - }); - - json.Array("Functions", [&Reflection, &json, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Reflection.Functions.size()); ++i) - PrintFunction(json, Reflection, i, IsVerbose, true); - }); - - // Already referenced indirectly through other properties we printed - // before, still printing it to allow consistency checks. - // For pure pretty prints, you should use the human version. - - json.Array("Parameters", [&Reflection, &json, hasSymbols, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Reflection.Parameters.size()); ++i) { - JsonWriter::ObjectScope nodeRoot(json); - - const DxcHLSLParameter ¶m = Reflection.Parameters[i]; - std::string paramName = - hasSymbols - ? Reflection.Strings[Reflection.NodeSymbols[param.NodeId] - .GetNameId()] - : std::to_string(i); - - json.StringField("ParamName", paramName); - - PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, json, - Reflection.Nodes[param.NodeId].GetSemanticId(), - param.InterpolationMode, param.Flags, true); - } - }); - - json.Array("Enums", [&Reflection, &json, hasSymbols, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Reflection.Enums.size()); ++i) - PrintEnum(json, Reflection, i, IsVerbose, true); - }); - - json.Array("EnumValues", [&Reflection, &json, hasSymbols, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Reflection.EnumValues.size()); ++i) { - JsonWriter::ObjectScope valueRoot(json); - PrintEnumValue(json, Reflection, Reflection.EnumValues[i].NodeId, - IsVerbose, true); - } - }); - - json.Array("Annotations", [&Reflection, &json, hasSymbols] { - for (uint32_t i = 0; i < uint32_t(Reflection.Annotations.size()); ++i) { - const DxcHLSLAnnotation &annot = Reflection.Annotations[i]; - JsonWriter::ObjectScope valueRoot(json); - json.UIntField("StringId", annot.GetStringNonDebug()); - PrintAnnotation(json, Reflection, annot); - } - }); - - json.Array("Arrays", [&Reflection, &json] { - for (uint32_t i = 0; i < uint32_t(Reflection.Arrays.size()); ++i) { - const DxcHLSLArray &arr = Reflection.Arrays[i]; - JsonWriter::ObjectScope valueRoot(json); - json.UIntField("ArrayElem", arr.ArrayElem()); - json.UIntField("ArrayStart", arr.ArrayStart()); - json.Array("ArraySizes", [&Reflection, &json, &arr] { - for (uint32_t i = 0; i < arr.ArrayElem(); ++i) { - json.Value(uint64_t(Reflection.ArraySizes[arr.ArrayStart() + i])); - } - }); - } - }); - - json.Array("ArraySizes", [&Reflection, &json] { - for (uint32_t id : Reflection.ArraySizes) - json.Value(uint64_t(id)); - }); - - json.Array("Members", [&Reflection, &json, hasSymbols, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Reflection.MemberTypeIds.size()); - ++i) { - - JsonWriter::ObjectScope valueRoot(json); - - if (hasSymbols) { - json.StringField("Name", - Reflection.Strings[Reflection.MemberNameIds[i]]); - json.UIntField("NameId", Reflection.MemberNameIds[i]); - } - - PrintTypeName(Reflection, Reflection.MemberTypeIds[i], hasSymbols, - IsVerbose, true, json, "TypeName"); - } - }); - - json.Array("TypeList", [&Reflection, &json, hasSymbols, IsVerbose] { - for (uint32_t id : Reflection.TypeList) { - JsonWriter::ObjectScope valueRoot(json); - PrintTypeName(Reflection, id, hasSymbols, IsVerbose, true, json); - } - }); - - json.Array("Types", [&Reflection, &json, hasSymbols, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Reflection.Types.size()); ++i) - PrintType(Reflection, i, hasSymbols, IsVerbose, true, json); - }); - - json.Array("Buffers", [&Reflection, &json, hasSymbols, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Reflection.Buffers.size()); ++i) - PrintBuffer(Reflection, i, hasSymbols, IsVerbose, true, json); - }); - - json.Array("Statements", [&Reflection, &json, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Reflection.Statements.size()); ++i) { - - const DxcHLSLStatement &stat = Reflection.Statements[i]; - JsonWriter::ObjectScope valueRoot(json); - json.StringField( - "Type", NodeTypeToString( - Reflection.Nodes[stat.GetNodeId()].GetNodeType())); - json.UIntField("NodeId", stat.GetNodeId()); - - PrintStatement(Reflection, stat, json, IsVerbose); - } - }); - } - - else { - // TODO: Print pretty tree for user - } - } - - return json.str(); -} - HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, ASTUnit::RemappedFile *pRemap, hlsl::options::DxcOpts &opts, DxcDefine *pDefines, @@ -2880,7 +1604,7 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, return E_FAIL; } - printf("%s\n", ToJson(refl, false, false).c_str()); + printf("%s\n", refl.ToJson(false, false).c_str()); // Test serialization @@ -2905,7 +1629,7 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, refl.StripSymbols(); - printf("%s\n", ToJson(refl, false, false).c_str()); + printf("%s\n", refl.ToJson(false, false).c_str()); refl.Dump(bytes); From 6cda035eb0b2a9055fb4a6fee45d9c2e37c3373e Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 20:49:46 +0100 Subject: [PATCH 077/126] Added human readable output of a reflection object --- .../tools/dxcreflection/DxcReflectionJson.cpp | 295 ++++++++++++++++-- tools/clang/tools/libclang/dxcreflector.cpp | 4 +- 2 files changed, 263 insertions(+), 36 deletions(-) diff --git a/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp index 0eb7aa5d07..a08e126bb7 100644 --- a/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp @@ -474,8 +474,6 @@ static void PrintNode(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, const DxcHLSLNode &node = Reflection.Nodes[NodeId]; - JsonWriter::ObjectScope nodeRoot(Json); - bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -544,11 +542,16 @@ static void PrintNode(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, Json.Object("Symbol", [&Reflection, &Json, NodeId, IsVerbose, AllRelevantMembers] { + const DxcHLSLNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; - Json.StringField("Name", Reflection.Strings[sym.GetNameId()]); - if (IsVerbose || AllRelevantMembers) - Json.UIntField("NameId", sym.GetNameId()); + if (sym.GetNameId() || IsVerbose) { + + Json.StringField("Name", Reflection.Strings[sym.GetNameId()]); + + if (IsVerbose || AllRelevantMembers) + Json.UIntField("NameId", sym.GetNameId()); + } if (sym.HasFileSource()) { @@ -560,7 +563,9 @@ static void PrintNode(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, Json.UIntField("SourceId", sym.GetFileSourceId()); Json.UIntField("LineId", sym.GetSourceLineStart()); - Json.UIntField("LineCount", sym.GetSourceLineCount()); + + if (sym.GetSourceLineCount() > 1 || IsVerbose) + Json.UIntField("LineCount", sym.GetSourceLineCount()); Json.UIntField("ColumnStart", sym.GetSourceColumnStart()); Json.UIntField("ColumnEnd", sym.GetSourceColumnEnd()); @@ -588,8 +593,6 @@ static void PrintRegister(JsonWriter &Json, const DxcHLSLReflectionData &Reflect const DxcHLSLRegister ® = Reflection.Registers[RegisterId]; - JsonWriter::ObjectScope nodeRoot(Json); - bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -598,14 +601,17 @@ static void PrintRegister(JsonWriter &Json, const DxcHLSLReflectionData &Reflect Json.UIntField("NodeId", reg.GetNodeId()); } - if (hasSymbols) - Json.StringField( - "Name", - Reflection - .Strings[Reflection.NodeSymbols[reg.GetNodeId()].GetNameId()]); + if (AllRelevantMembers) { - else if (IsVerbose) - Json.StringField("Name", ""); + if (hasSymbols) + Json.StringField( + "Name", + Reflection + .Strings[Reflection.NodeSymbols[reg.GetNodeId()].GetNameId()]); + + else if (IsVerbose) + Json.StringField("Name", ""); + } Json.StringField("RegisterType", RegisterTypeToString(reg.GetType())); @@ -728,7 +734,6 @@ static void PrintType(const DxcHLSLReflectionData &Reflection, uint32_t TypeId, const DxcHLSLType &type = Reflection.Types[TypeId]; - JsonWriter::ObjectScope nodeRoot(Json); PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, Json); @@ -827,8 +832,6 @@ static void PrintFunction(JsonWriter &Json, const DxcHLSLReflectionData &Reflect const DxcHLSLFunction &func = Reflection.Functions[FunctionId]; - JsonWriter::ObjectScope nodeRoot(Json); - bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -837,14 +840,16 @@ static void PrintFunction(JsonWriter &Json, const DxcHLSLReflectionData &Reflect Json.UIntField("NodeId", func.GetNodeId()); } - if (hasSymbols) - Json.StringField( - "Name", - Reflection - .Strings[Reflection.NodeSymbols[func.GetNodeId()].GetNameId()]); + if (AllRelevantMembers) { + if (hasSymbols) + Json.StringField( + "Name", + Reflection + .Strings[Reflection.NodeSymbols[func.GetNodeId()].GetNameId()]); - else if (IsVerbose) - Json.StringField("Name", ""); + else if (IsVerbose) + Json.StringField("Name", ""); + } Json.BoolField("HasDefinition", func.HasDefinition()); @@ -932,7 +937,6 @@ static void PrintEnum(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, uint32_t EnumId, bool IsVerbose, bool AllRelevantMembers) { - JsonWriter::ObjectScope nodeRoot(Json); const DxcHLSLEnumDesc &enm = Reflection.Enums[EnumId]; const DxcHLSLNode &node = Reflection.Nodes[enm.NodeId]; @@ -1111,6 +1115,215 @@ static void PrintStatement(const DxcHLSLReflectionData &Reflection, Json.UIntField("NodesB", nodesB); } +uint32_t PrintNodeRecursive(const DxcHLSLReflectionData &Reflection, + uint32_t NodeId, JsonWriter &Json, bool IsVerbose, + bool IsHumanFriendly) { + + bool hasSymbols = + Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + + //Self + + DxcHLSLNode node = Reflection.Nodes[NodeId]; + D3D12_HLSL_NODE_TYPE nodeType = node.GetNodeType(); + + if (node.IsFwdDeclare()) { + NodeId = node.GetFwdBck(); + node = Reflection.Nodes[NodeId]; + } + + PrintNode(Json, Reflection, NodeId, IsVerbose, !IsHumanFriendly); + + uint32_t childrenToSkip = 0; + + //Function + + if (nodeType == D3D12_HLSL_NODE_TYPE_FUNCTION) + Json.Object("Function", [&node, &Reflection, &Json, IsVerbose, + IsHumanFriendly, &childrenToSkip]() { + DxcHLSLFunction func = Reflection.Functions[node.GetLocalId()]; + PrintFunction(Json, Reflection, node.GetLocalId(), IsVerbose, + !IsHumanFriendly); + childrenToSkip = func.GetNumParameters() + func.HasReturn(); + }); + + else if (IsVerbose) + Json.NullField("Function"); + + //Register + + if (nodeType == D3D12_HLSL_NODE_TYPE_REGISTER) + Json.Object("Register", + [&node, &Reflection, &Json, IsVerbose, IsHumanFriendly]() { + PrintRegister(Json, Reflection, node.GetLocalId(), IsVerbose, + !IsHumanFriendly); + }); + + else if (IsVerbose) + Json.NullField("Register"); + + //Enum + + if (nodeType == D3D12_HLSL_NODE_TYPE_ENUM) + Json.Object("Enum", [&node, &Reflection, &Json, IsVerbose, IsHumanFriendly, + &childrenToSkip]() { + PrintEnum(Json, Reflection, node.GetLocalId(), IsVerbose, + !IsHumanFriendly); + childrenToSkip = node.GetChildCount(); + }); + + else if (IsVerbose) + Json.NullField("Enum"); + + //Type + + bool isType = false; + + switch (nodeType) { + case D3D12_HLSL_NODE_TYPE_TYPEDEF: + case D3D12_HLSL_NODE_TYPE_VARIABLE: + case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: + case D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE: + isType = true; + break; + } + + if (isType) + Json.Object("Type", [&node, &Reflection, &Json, IsVerbose, IsHumanFriendly, + hasSymbols]() { + PrintType(Reflection, node.GetLocalId(), hasSymbols, IsVerbose, + !IsHumanFriendly, Json); + }); + + else if (IsVerbose) + Json.NullField("Type"); + + //If; turns into ("Condition"), ("Body"), ("Else") + //While; turns into ("Condition"), ("Body") + //For; turns into ("Condition"), ("Init"), ("Body") + //Switch; turns into ("Condition"), ("Body") + + const char *stmtType = nullptr; + + switch (nodeType) { + + case D3D12_HLSL_NODE_TYPE_IF: + stmtType = "If"; + break; + + case D3D12_HLSL_NODE_TYPE_SWITCH: + stmtType = "Switch"; + break; + + case D3D12_HLSL_NODE_TYPE_FOR: + stmtType = "For"; + break; + + case D3D12_HLSL_NODE_TYPE_WHILE: + stmtType = "While"; + break; + } + + if (stmtType) { + + if (IsVerbose) { + + if (nodeType != D3D12_HLSL_NODE_TYPE_IF) + Json.NullField("If"); + + if (nodeType != D3D12_HLSL_NODE_TYPE_WHILE) + Json.NullField("While"); + + if (nodeType != D3D12_HLSL_NODE_TYPE_SWITCH) + Json.NullField("Switch"); + + if (nodeType != D3D12_HLSL_NODE_TYPE_FOR) + Json.NullField("For"); + } + + Json.Object(stmtType, [&node, &Reflection, &Json, IsVerbose, + IsHumanFriendly, NodeId, &childrenToSkip, nodeType]() { + const DxcHLSLStatement &stmt = Reflection.Statements[node.GetLocalId()]; + + uint32_t start = NodeId + 1; + + if (stmt.HasConditionVar()) + Json.Object("Condition", [NodeId, &Reflection, &Json, IsVerbose, + IsHumanFriendly, &start]() { + start += PrintNodeRecursive(Reflection, start, Json, IsVerbose, + IsHumanFriendly); + ++start; + }); + + else if (IsVerbose) + Json.NullField("Condition"); + + uint32_t end = start + stmt.GetNodeCount(); + + bool isIf = nodeType == D3D12_HLSL_NODE_TYPE_IF; + const char *bodyName = isIf ? "Body" : "Init"; + + if (stmt.GetNodeCount()) + Json.Array(bodyName, [&Reflection, &Json, IsVerbose, start, end, + IsHumanFriendly, NodeId]() { + for (uint32_t i = start; i < end; ++i) { + JsonWriter::ObjectScope valueRoot(Json); + i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, + IsHumanFriendly); + } + }); + + else if (IsVerbose) + Json.NullField(bodyName); + + const char *elseName = isIf ? "Else" : "Body"; + + if (stmt.HasElse() || !isIf) { + + start = end; + end = NodeId + 1 + node.GetChildCount(); + + Json.Array(elseName, [&Reflection, &Json, IsVerbose, start, end, + IsHumanFriendly, NodeId]() { + for (uint32_t i = start; i < end; ++i) { + JsonWriter::ObjectScope valueRoot(Json); + i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, + IsHumanFriendly); + } + }); + } + + else if (IsVerbose) + Json.NullField(elseName); + + childrenToSkip = node.GetChildCount(); + }); + } + + else if (IsVerbose) { + Json.NullField("If"); + Json.NullField("While"); + Json.NullField("Switch"); + Json.NullField("For"); + } + + //Children + + uint32_t start = NodeId + 1 + childrenToSkip; + uint32_t end = NodeId + 1 + node.GetChildCount(); + + if (end > start) + Json.Array("Children", [&Reflection, &Json, IsVerbose, start, end, + IsHumanFriendly]() { + for (uint32_t i = start; i < end; ++i) { + JsonWriter::ObjectScope valueRoot(Json); + i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, IsHumanFriendly); + } + }); + + return node.GetChildCount(); +} + //IsHumanFriendly = false: Raw view of the real file data //IsHumanFriendly = true: Clean view that's relatively close to the real tree std::string DxcHLSLReflectionData::ToJson( @@ -1153,18 +1366,24 @@ std::string DxcHLSLReflectionData::ToJson( }); json.Array("Nodes", [this, &json, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Nodes.size()); ++i) + for (uint32_t i = 0; i < uint32_t(Nodes.size()); ++i) { + JsonWriter::ObjectScope nodeRoot(json); PrintNode(json, *this, i, IsVerbose, true); + } }); json.Array("Registers", [this, &json, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Registers.size()); ++i) + for (uint32_t i = 0; i < uint32_t(Registers.size()); ++i) { + JsonWriter::ObjectScope nodeRoot(json); PrintRegister(json, *this, i, IsVerbose, true); + } }); json.Array("Functions", [this, &json, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Functions.size()); ++i) + for (uint32_t i = 0; i < uint32_t(Functions.size()); ++i) { + JsonWriter::ObjectScope nodeRoot(json); PrintFunction(json, *this, i, IsVerbose, true); + } }); // Already referenced indirectly through other properties we printed @@ -1189,8 +1408,10 @@ std::string DxcHLSLReflectionData::ToJson( }); json.Array("Enums", [this, &json, hasSymbols, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Enums.size()); ++i) + for (uint32_t i = 0; i < uint32_t(Enums.size()); ++i) { + JsonWriter::ObjectScope nodeRoot(json); PrintEnum(json, *this, i, IsVerbose, true); + } }); json.Array("EnumValues", [this, &json, hasSymbols, IsVerbose] { @@ -1252,8 +1473,10 @@ std::string DxcHLSLReflectionData::ToJson( }); json.Array("Types", [this, &json, hasSymbols, IsVerbose] { - for (uint32_t i = 0; i < uint32_t(Types.size()); ++i) + for (uint32_t i = 0; i < uint32_t(Types.size()); ++i) { + JsonWriter::ObjectScope nodeRoot(json); PrintType(*this, i, hasSymbols, IsVerbose, true, json); + } }); json.Array("Buffers", [this, &json, hasSymbols, IsVerbose] { @@ -1276,9 +1499,13 @@ std::string DxcHLSLReflectionData::ToJson( }); } - else { - // TODO: Print pretty tree for user - } + else + json.Array("Children", [this, &json, IsVerbose]() { + for (uint32_t i = 1; i < Nodes.size(); ++i) { + JsonWriter::ObjectScope valueRoot(json); + i += PrintNodeRecursive(*this, i, json, IsVerbose, true); + } + }); } return json.str(); diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/libclang/dxcreflector.cpp index cbb4e1cb2e..f8d91224c0 100644 --- a/tools/clang/tools/libclang/dxcreflector.cpp +++ b/tools/clang/tools/libclang/dxcreflector.cpp @@ -1604,7 +1604,7 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, return E_FAIL; } - printf("%s\n", refl.ToJson(false, false).c_str()); + printf("%s\n", refl.ToJson().c_str()); // Test serialization @@ -1629,7 +1629,7 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, refl.StripSymbols(); - printf("%s\n", refl.ToJson(false, false).c_str()); + printf("%s\n", refl.ToJson().c_str()); refl.Dump(bytes); From f83c920ccc360f236aa130bcfd83e8745de500a3 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 22:27:01 +0100 Subject: [PATCH 078/126] Added recursive type printing and replaced buffer's recursive type printing with real type printing. Also fixed definitions if there's a fwd declare (they need to be ignored) --- .../tools/dxcreflection/DxcReflectionJson.cpp | 114 ++++++++---------- 1 file changed, 50 insertions(+), 64 deletions(-) diff --git a/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp index a08e126bb7..eb62c05354 100644 --- a/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp @@ -730,18 +730,24 @@ static void PrintTypeName(const DxcHLSLReflectionData &Reflection, uint32_t Type static void PrintType(const DxcHLSLReflectionData &Reflection, uint32_t TypeId, bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, - JsonWriter &Json) { + JsonWriter &Json, bool Recursive, + const char *NameForTypeName = "Name") { const DxcHLSLType &type = Reflection.Types[TypeId]; PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, - Json); + Json, NameForTypeName); if (type.GetBaseClass() != uint32_t(-1)) Json.Object("BaseClass", [&Reflection, &Json, &type, HasSymbols, IsVerbose, - AllRelevantMembers]() { - PrintTypeName(Reflection, type.GetBaseClass(), HasSymbols, IsVerbose, - AllRelevantMembers, Json); + AllRelevantMembers, Recursive]() { + if (Recursive) + PrintType(Reflection, type.GetBaseClass(), HasSymbols, IsVerbose, + AllRelevantMembers, Json, true, "TypeName"); + + else + PrintTypeName(Reflection, type.GetBaseClass(), HasSymbols, IsVerbose, + AllRelevantMembers, Json, "TypeName"); }); else if (IsVerbose) @@ -763,7 +769,7 @@ static void PrintType(const DxcHLSLReflectionData &Reflection, uint32_t TypeId, if (type.GetMemberCount()) Json.Array("Members", [&Reflection, &Json, &type, HasSymbols, IsVerbose, - AllRelevantMembers]() { + AllRelevantMembers, Recursive]() { for (uint32_t i = 0; i < uint32_t(type.GetMemberCount()); ++i) { uint32_t memberId = type.GetMemberStart() + i; @@ -775,9 +781,14 @@ static void PrintType(const DxcHLSLReflectionData &Reflection, uint32_t TypeId, Json.UIntField("NameId", Reflection.MemberNameIds[memberId]); } - PrintTypeName(Reflection, Reflection.MemberTypeIds[memberId], - HasSymbols, IsVerbose, AllRelevantMembers, Json, - "TypeName"); + if (Recursive) + PrintType(Reflection, Reflection.MemberTypeIds[memberId], HasSymbols, + IsVerbose, AllRelevantMembers, Json, true, "TypeName"); + + else + PrintTypeName(Reflection, Reflection.MemberTypeIds[memberId], + HasSymbols, IsVerbose, AllRelevantMembers, Json, + "TypeName"); } }); @@ -883,7 +894,17 @@ static void PrintFunction(JsonWriter &Json, const DxcHLSLReflectionData &Reflect }); if (!func.HasReturn()) - Json.StringField("ReturnType", "void"); + Json.Object("ReturnType", [&Json, IsVerbose]() { + + Json.StringField("TypeName", "void"); + + if (IsVerbose) { + Json.IntField("TypeId", -1); + Json.Array("ArraySize", []() {}); + Json.StringField("UnderlyingName", "void"); + Json.Array("UnderlyingArraySize", []() {}); + } + }); else { @@ -981,43 +1002,6 @@ static void PrintAnnotation(JsonWriter &Json, const DxcHLSLReflectionData &Refle Json.StringField("Type", Annot.GetIsBuiltin() ? "Builtin" : "User"); } -static void PrintBufferMemberMember(const DxcHLSLReflectionData &Reflection, - bool HasSymbols, bool IsVerbose, - bool AllRelevantMembers, JsonWriter &Json, - uint32_t ChildId, uint32_t MemberId) { - - uint32_t TypeId = Reflection.MemberTypeIds[MemberId]; - - JsonWriter::ObjectScope nodeRoot(Json); - - if (IsVerbose || AllRelevantMembers || !HasSymbols) - Json.UIntField("ChildId", ChildId); - - if (HasSymbols) - Json.StringField("Name", - Reflection.Strings[Reflection.MemberNameIds[MemberId]]); - - else if (IsVerbose) - Json.StringField("Name", ""); - - const DxcHLSLType &type = Reflection.Types[TypeId]; - - PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, - Json, "TypeName"); - - if (type.GetMemberCount()) - Json.Array("Children", [&type, &Reflection, &Json, HasSymbols, IsVerbose, - AllRelevantMembers]() { - for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { - - uint32_t memberId = type.GetMemberStart() + i; - - PrintBufferMemberMember(Reflection, HasSymbols, IsVerbose, - AllRelevantMembers, Json, i, memberId); - } - }); -} - static uint32_t PrintBufferMember(const DxcHLSLReflectionData &Reflection, uint32_t NodeId, uint32_t ChildId, bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, @@ -1040,19 +1024,8 @@ static uint32_t PrintBufferMember(const DxcHLSLReflectionData &Reflection, else if (IsVerbose) Json.StringField("Name", ""); - PrintTypeName(Reflection, node.GetLocalId(), HasSymbols, IsVerbose, - AllRelevantMembers, Json, "TypeName"); - - const DxcHLSLType &type = Reflection.Types[node.GetLocalId()]; - - if (type.GetMemberCount() || IsVerbose) - Json.Array("Children", [&type, &Reflection, &Json, HasSymbols, IsVerbose, - AllRelevantMembers]() { - for (uint32_t i = 0; i < type.GetMemberCount(); ++i) - PrintBufferMemberMember(Reflection, HasSymbols, IsVerbose, - AllRelevantMembers, Json, i, - type.GetMemberStart() + i); - }); + PrintType(Reflection, node.GetLocalId(), HasSymbols, IsVerbose, + AllRelevantMembers, Json, true, "TypeName"); return node.GetChildCount(); } @@ -1119,12 +1092,20 @@ uint32_t PrintNodeRecursive(const DxcHLSLReflectionData &Reflection, uint32_t NodeId, JsonWriter &Json, bool IsVerbose, bool IsHumanFriendly) { + bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; //Self DxcHLSLNode node = Reflection.Nodes[NodeId]; + + // If this happens, we found the one defining a fwd declare. + // But this can happen in a different scope than the symbol ends up in. + // Mute this node. + if (node.IsFwdBckDefined() && !node.IsFwdDeclare()) + return node.GetChildCount(); + D3D12_HLSL_NODE_TYPE nodeType = node.GetNodeType(); if (node.IsFwdDeclare()) { @@ -1178,21 +1159,26 @@ uint32_t PrintNodeRecursive(const DxcHLSLReflectionData &Reflection, //Type bool isType = false; + bool recurseType = false; switch (nodeType) { - case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: case D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE: + recurseType = true; + isType = true; + break; + + case D3D12_HLSL_NODE_TYPE_TYPEDEF: isType = true; break; } if (isType) Json.Object("Type", [&node, &Reflection, &Json, IsVerbose, IsHumanFriendly, - hasSymbols]() { + hasSymbols, recurseType]() { PrintType(Reflection, node.GetLocalId(), hasSymbols, IsVerbose, - !IsHumanFriendly, Json); + !IsHumanFriendly, Json, recurseType); }); else if (IsVerbose) @@ -1475,7 +1461,7 @@ std::string DxcHLSLReflectionData::ToJson( json.Array("Types", [this, &json, hasSymbols, IsVerbose] { for (uint32_t i = 0; i < uint32_t(Types.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintType(*this, i, hasSymbols, IsVerbose, true, json); + PrintType(*this, i, hasSymbols, IsVerbose, true, json, false); } }); From 137dcab63cb610bebb7d665a6a8f76d37ca5652f Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 22:40:05 +0100 Subject: [PATCH 079/126] Now printing symbol for function params, enum values --- .../tools/dxcreflection/DxcReflectionJson.cpp | 121 +++++++++++------- 1 file changed, 74 insertions(+), 47 deletions(-) diff --git a/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp index eb62c05354..20c0e0130d 100644 --- a/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp @@ -466,6 +466,49 @@ static void FillArraySizes(const DxcHLSLReflectionData &Reflection, Array.push_back(Reflection.ArraySizes[arr.ArrayStart() + i]); } +static void PrintSymbol(JsonWriter &Json, + const DxcHLSLReflectionData &Reflection, + const DxcHLSLNodeSymbol &Sym, bool IsVerbose, + bool AllRelevantMembers, bool MuteName = false) { + + if ((Sym.GetNameId() || IsVerbose) && !MuteName) { + + Json.StringField("Name", Reflection.Strings[Sym.GetNameId()]); + + if (IsVerbose || AllRelevantMembers) + Json.UIntField("NameId", Sym.GetNameId()); + } + + if (Sym.HasFileSource()) { + + Json.StringField( + "Source", + Reflection.Strings[Reflection.Sources[Sym.GetFileSourceId()]]); + + if (IsVerbose || AllRelevantMembers) + Json.UIntField("SourceId", Sym.GetFileSourceId()); + + Json.UIntField("LineId", Sym.GetSourceLineStart()); + + if (Sym.GetSourceLineCount() > 1 || IsVerbose) + Json.UIntField("LineCount", Sym.GetSourceLineCount()); + + Json.UIntField("ColumnStart", Sym.GetSourceColumnStart()); + Json.UIntField("ColumnEnd", Sym.GetSourceColumnEnd()); + + } else if (IsVerbose) { + + Json.StringField("Source", ""); + Json.IntField("SourceId", -1); + + Json.IntField("LineId", -1); + Json.UIntField("LineCount", 0); + + Json.IntField("ColumnStart", -1); + Json.UIntField("ColumnEnd", 0); + } +} + //Verbose and all members are slightly different; //Verbose will still print fields even if they aren't relevant, // while all members will not silence important info but that might not matter for human readability @@ -542,45 +585,8 @@ static void PrintNode(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, Json.Object("Symbol", [&Reflection, &Json, NodeId, IsVerbose, AllRelevantMembers] { - const DxcHLSLNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; - - if (sym.GetNameId() || IsVerbose) { - - Json.StringField("Name", Reflection.Strings[sym.GetNameId()]); - - if (IsVerbose || AllRelevantMembers) - Json.UIntField("NameId", sym.GetNameId()); - } - - if (sym.HasFileSource()) { - - Json.StringField( - "Source", - Reflection.Strings[Reflection.Sources[sym.GetFileSourceId()]]); - - if (IsVerbose || AllRelevantMembers) - Json.UIntField("SourceId", sym.GetFileSourceId()); - - Json.UIntField("LineId", sym.GetSourceLineStart()); - - if (sym.GetSourceLineCount() > 1 || IsVerbose) - Json.UIntField("LineCount", sym.GetSourceLineCount()); - - Json.UIntField("ColumnStart", sym.GetSourceColumnStart()); - Json.UIntField("ColumnEnd", sym.GetSourceColumnEnd()); - - } else if (IsVerbose) { - - Json.StringField("Source", ""); - Json.IntField("SourceId", -1); - - Json.IntField("LineId", -1); - Json.UIntField("LineCount", 0); - - Json.IntField("ColumnStart", -1); - Json.UIntField("ColumnEnd", 0); - } + PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers); }); } else if (IsVerbose) @@ -885,7 +891,22 @@ static void PrintFunction(JsonWriter &Json, const DxcHLSLReflectionData &Reflect Json.Object(paramName.c_str(), [&Reflection, &func, &Json, hasSymbols, IsVerbose, ¶m, &node, - AllRelevantMembers]() { + AllRelevantMembers, nodeId]() { + + if (hasSymbols) { + + const DxcHLSLNodeSymbol &sym = Reflection.NodeSymbols[nodeId]; + + Json.Object("Symbol", [&Json, &Reflection, &sym, IsVerbose, + AllRelevantMembers]() { + PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers, + true); + }); + } + + else if (IsVerbose) + Json.NullField("Symbol"); + PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, Json, node.GetSemanticId(), param.InterpolationMode, param.Flags, AllRelevantMembers); @@ -922,10 +943,10 @@ static void PrintFunction(JsonWriter &Json, const DxcHLSLReflectionData &Reflect } static void PrintEnumValue(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, - uint32_t ChildId, bool IsVerbose, + uint32_t NodeId, bool IsVerbose, bool AllRelevantMembers) { - const DxcHLSLNode &child = Reflection.Nodes[ChildId]; + const DxcHLSLNode &child = Reflection.Nodes[NodeId]; const DxcHLSLEnumValue &val = Reflection.EnumValues[child.GetLocalId()]; @@ -946,12 +967,18 @@ static void PrintEnumValue(JsonWriter &Json, const DxcHLSLReflectionData &Reflec bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (hasSymbols || IsVerbose) - Json.StringField( - "Name", - !hasSymbols - ? "" - : Reflection.Strings[Reflection.NodeSymbols[ChildId].GetNameId()]); + if (hasSymbols) { + + const DxcHLSLNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; + + Json.Object( + "Symbol", [&Json, &Reflection, &sym, IsVerbose, AllRelevantMembers]() { + PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers); + }); + } + + else if (IsVerbose) + Json.NullField("Symbol"); } static void PrintEnum(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, From f7d0b4a538ef47a15121ac68d27dd6c5e060bd7a Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 22:49:38 +0100 Subject: [PATCH 080/126] Moved dxcreflection to dxcreflectioncontainer, so new dxcreflection will become the whole clang integration --- tools/clang/tools/CMakeLists.txt | 2 +- .../{dxcreflection => dxcreflectioncontainer}/CMakeLists.txt | 2 +- .../{dxcreflection => dxcreflectioncontainer}/DxcReflection.cpp | 0 .../DxcReflectionJson.cpp | 0 tools/clang/tools/libclang/CMakeLists.txt | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) rename tools/clang/tools/{dxcreflection => dxcreflectioncontainer}/CMakeLists.txt (65%) rename tools/clang/tools/{dxcreflection => dxcreflectioncontainer}/DxcReflection.cpp (100%) rename tools/clang/tools/{dxcreflection => dxcreflectioncontainer}/DxcReflectionJson.cpp (100%) diff --git a/tools/clang/tools/CMakeLists.txt b/tools/clang/tools/CMakeLists.txt index 8149beea10..24542237d7 100644 --- a/tools/clang/tools/CMakeLists.txt +++ b/tools/clang/tools/CMakeLists.txt @@ -4,7 +4,7 @@ add_subdirectory(driver) # add_subdirectory(clang-fuzzer) # HLSL Change # add_subdirectory(c-index-test) # HLSL Change -add_subdirectory(dxcreflection) # HLSL Change +add_subdirectory(dxcreflectioncontainer) # HLSL Change add_subdirectory(libclang) if(0 AND CLANG_ENABLE_ARCMT) # HLSL Change diff --git a/tools/clang/tools/dxcreflection/CMakeLists.txt b/tools/clang/tools/dxcreflectioncontainer/CMakeLists.txt similarity index 65% rename from tools/clang/tools/dxcreflection/CMakeLists.txt rename to tools/clang/tools/dxcreflectioncontainer/CMakeLists.txt index dc54faa64f..af848d992b 100644 --- a/tools/clang/tools/dxcreflection/CMakeLists.txt +++ b/tools/clang/tools/dxcreflectioncontainer/CMakeLists.txt @@ -1,4 +1,4 @@ # Copyright (C) Microsoft Corporation. All rights reserved. # This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. -add_clang_library(dxcreflection STATIC DxcReflection.cpp DxcReflectionJson.cpp) +add_clang_library(dxcreflectioncontainer STATIC DxcReflection.cpp DxcReflectionJson.cpp) diff --git a/tools/clang/tools/dxcreflection/DxcReflection.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflection.cpp similarity index 100% rename from tools/clang/tools/dxcreflection/DxcReflection.cpp rename to tools/clang/tools/dxcreflectioncontainer/DxcReflection.cpp diff --git a/tools/clang/tools/dxcreflection/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp similarity index 100% rename from tools/clang/tools/dxcreflection/DxcReflectionJson.cpp rename to tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp diff --git a/tools/clang/tools/libclang/CMakeLists.txt b/tools/clang/tools/libclang/CMakeLists.txt index f183e1ab17..6a902693c0 100644 --- a/tools/clang/tools/libclang/CMakeLists.txt +++ b/tools/clang/tools/libclang/CMakeLists.txt @@ -183,7 +183,7 @@ endif() endif() # HLSL Change add_dependencies(libclang TablegenHLSLOptions) # HLSL Change -target_link_libraries(libclang PRIVATE dxcreflection) # HLSL Change +target_link_libraries(libclang PRIVATE dxcreflectioncontainer) # HLSL Change # HLSL Change Starts # add_clang_library(${LIBCLANG_STATIC_TARGET_NAME} STATIC ${SOURCES}) From 8f69e6443e1e709c1a4e7bc846cd0aa25be7c53c Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 22:59:54 +0100 Subject: [PATCH 081/126] Moved dxcreflector into its own library from libclang --- tools/clang/tools/CMakeLists.txt | 1 + tools/clang/tools/dxcreflection/CMakeLists.txt | 15 +++++++++++++++ .../dxcreflection_from_ast.cpp | 0 .../{libclang => dxcreflection}/dxcreflector.cpp | 0 tools/clang/tools/libclang/CMakeLists.txt | 6 +----- 5 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 tools/clang/tools/dxcreflection/CMakeLists.txt rename tools/clang/tools/{libclang => dxcreflection}/dxcreflection_from_ast.cpp (100%) rename tools/clang/tools/{libclang => dxcreflection}/dxcreflector.cpp (100%) diff --git a/tools/clang/tools/CMakeLists.txt b/tools/clang/tools/CMakeLists.txt index 24542237d7..b54efd7f45 100644 --- a/tools/clang/tools/CMakeLists.txt +++ b/tools/clang/tools/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory(driver) # add_subdirectory(c-index-test) # HLSL Change add_subdirectory(dxcreflectioncontainer) # HLSL Change +add_subdirectory(dxcreflection) # HLSL Change add_subdirectory(libclang) if(0 AND CLANG_ENABLE_ARCMT) # HLSL Change diff --git a/tools/clang/tools/dxcreflection/CMakeLists.txt b/tools/clang/tools/dxcreflection/CMakeLists.txt new file mode 100644 index 0000000000..03d340ca58 --- /dev/null +++ b/tools/clang/tools/dxcreflection/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) Microsoft Corporation. All rights reserved. +# This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. + +set(LIBRARIES + clangFrontend + clangAST + clangBasic + clangLex + ) + +add_clang_library(dxcreflection STATIC + dxcreflector.cpp + dxcreflection_from_ast.cpp) + +target_link_libraries(dxcreflection PRIVATE ${LIBRARIES} dxcreflectioncontainer) diff --git a/tools/clang/tools/libclang/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp similarity index 100% rename from tools/clang/tools/libclang/dxcreflection_from_ast.cpp rename to tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp diff --git a/tools/clang/tools/libclang/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp similarity index 100% rename from tools/clang/tools/libclang/dxcreflector.cpp rename to tools/clang/tools/dxcreflection/dxcreflector.cpp diff --git a/tools/clang/tools/libclang/CMakeLists.txt b/tools/clang/tools/libclang/CMakeLists.txt index 6a902693c0..724d24ccc8 100644 --- a/tools/clang/tools/libclang/CMakeLists.txt +++ b/tools/clang/tools/libclang/CMakeLists.txt @@ -30,8 +30,6 @@ set(SOURCES IndexingContext.cpp dxcisenseimpl.cpp # HLSL Change dxcrewriteunused.cpp # HLSL Change - dxcreflector.cpp # HLSL Change - dxcreflection_from_ast.cpp # HLSL Change ADDITIONAL_HEADERS CIndexDiagnostic.h @@ -72,8 +70,6 @@ set(SOURCES IndexingContext.cpp dxcisenseimpl.cpp # HLSL Change dxcrewriteunused.cpp # HLSL Change - dxcreflector.cpp # HLSL Change - dxcreflection_from_ast.cpp # HLSL Change ADDITIONAL_HEADERS CIndexDiagnostic.h @@ -183,7 +179,7 @@ endif() endif() # HLSL Change add_dependencies(libclang TablegenHLSLOptions) # HLSL Change -target_link_libraries(libclang PRIVATE dxcreflectioncontainer) # HLSL Change +target_link_libraries(libclang PRIVATE dxcreflection) # HLSL Change # HLSL Change Starts # add_clang_library(${LIBCLANG_STATIC_TARGET_NAME} STATIC ${SOURCES}) From 715265eb7284edbcf8c5e1698980a6c620b44423 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 23:07:52 +0100 Subject: [PATCH 082/126] Moved dxcreflect out of dxctools --- include/dxc/DxcReflection/DxcReflection.h | 2 +- include/dxc/dxcreflect.h | 355 ++++++++++++++++++ include/dxc/dxctools.h | 331 ---------------- tools/clang/tools/dxcompiler/dxcapi.cpp | 1 + .../tools/dxcreflection/dxcreflector.cpp | 2 +- tools/clang/tools/dxreflector/dxreflector.cpp | 2 +- 6 files changed, 359 insertions(+), 334 deletions(-) create mode 100644 include/dxc/dxcreflect.h diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflection.h index 9bd006ace7..796debd376 100644 --- a/include/dxc/DxcReflection/DxcReflection.h +++ b/include/dxc/DxcReflection/DxcReflection.h @@ -16,7 +16,7 @@ #include #include "d3d12shader.h" -#include "dxc/dxctools.h" +#include "dxc/dxcreflect.h" #pragma warning(disable : 4201) diff --git a/include/dxc/dxcreflect.h b/include/dxc/dxcreflect.h new file mode 100644 index 0000000000..43e20ea1e2 --- /dev/null +++ b/include/dxc/dxcreflect.h @@ -0,0 +1,355 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// dxcreflect.h // +// Copyright (C) Microsoft Corporation. All rights reserved. // +// This file is distributed under the University of Illinois Open Source // +// License. See LICENSE.TXT for details. // +// // +// Provides declarations for the DirectX Compiler reflection components. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __DXC_REFLECT__ +#define __DXC_REFLECT__ + +#include +#include "d3d12shader.h" + +#ifdef _MSC_VER +#define CLSID_SCOPE __declspec(selectany) extern +#else +#define CLSID_SCOPE +#endif + +//Expose HLSL reflection before DXIL/SPIRV generation. +//(Ran after the preprocessed HLSL is obtained). +//This is useful to avoid custom parsers from reinventing the wheel. +//You could use it to find all entrypoints even if [shader("")] isn't used, +//Find struct/enum information, find out about optimized out registers, etc. + +enum D3D12_HLSL_REFLECTION_FEATURE { + + D3D12_HLSL_REFLECTION_FEATURE_NONE = 0, + + // Includes cbuffer and registers only + D3D12_HLSL_REFLECTION_FEATURE_BASICS = 1 << 0, + + D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS = 1 << 1, + D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES = 1 << 2, + + // Include user types (struct, enum, typedef, etc.) + D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES = 1 << 3, + + // Variables, structs, functions defined in functions + D3D12_HLSL_REFLECTION_FEATURE_SCOPES = 1 << 4, + + // Symbol info (stripping this will remove names and file location info) + D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO = 1 << 16, + + D3D12_HLSL_REFLECTION_FEATURE_ALL = D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - 1 +}; + +inline D3D12_HLSL_REFLECTION_FEATURE &operator|=(D3D12_HLSL_REFLECTION_FEATURE &a, + D3D12_HLSL_REFLECTION_FEATURE b) { + return a = (D3D12_HLSL_REFLECTION_FEATURE)(uint32_t(a) | uint32_t(b)); +} + +inline D3D12_HLSL_REFLECTION_FEATURE & +operator&=(D3D12_HLSL_REFLECTION_FEATURE &a, + D3D12_HLSL_REFLECTION_FEATURE b) { + return a = (D3D12_HLSL_REFLECTION_FEATURE)(uint32_t(a) & uint32_t(b)); +} + +inline D3D12_HLSL_REFLECTION_FEATURE +operator~(D3D12_HLSL_REFLECTION_FEATURE a) { + return (D3D12_HLSL_REFLECTION_FEATURE) ~uint32_t(a); +} + +struct D3D12_HLSL_REFLECTION_DESC { + D3D12_HLSL_REFLECTION_FEATURE Features; + UINT ConstantBufferCount; + UINT ResourceCount; + UINT FunctionCount; + UINT EnumCount; + UINT NodeCount; + UINT TypeCount; + UINT StructCount; + UINT UnionCount; + UINT InterfaceCount; +}; + +struct D3D12_HLSL_FUNCTION_DESC { + LPCSTR Name; // Function name + UINT FunctionParameterCount; // Number of logical parameters in the function + // signature (not including return) + BOOL HasReturn; // TRUE, if function returns a value, false - it is a + // subroutine +}; + +enum D3D12_HLSL_ENUM_TYPE { + + D3D12_HLSL_ENUM_TYPE_UINT, + D3D12_HLSL_ENUM_TYPE_INT, + D3D12_HLSL_ENUM_TYPE_UINT64_T, + D3D12_HLSL_ENUM_TYPE_INT64_T, + D3D12_HLSL_ENUM_TYPE_UINT16_T, + D3D12_HLSL_ENUM_TYPE_INT16_T, + + D3D12_HLSL_ENUM_TYPE_START = D3D12_HLSL_ENUM_TYPE_UINT, + D3D12_HLSL_ENUM_TYPE_END = D3D12_HLSL_ENUM_TYPE_INT16_T +}; + +struct D3D12_HLSL_ENUM_DESC { + LPCSTR Name; + UINT ValueCount; + D3D12_HLSL_ENUM_TYPE Type; +}; + +struct D3D12_HLSL_ENUM_VALUE { + LPCSTR Name; + INT64 Value; +}; + +struct D3D12_HLSL_ANNOTATION { + LPCSTR Name; + BOOL IsBuiltin; +}; + +enum D3D12_HLSL_NODE_TYPE { + + D3D12_HLSL_NODE_TYPE_REGISTER, + D3D12_HLSL_NODE_TYPE_FUNCTION, + D3D12_HLSL_NODE_TYPE_ENUM, + D3D12_HLSL_NODE_TYPE_ENUM_VALUE, + D3D12_HLSL_NODE_TYPE_NAMESPACE, + + D3D12_HLSL_NODE_TYPE_VARIABLE, // localId points to the type + D3D12_HLSL_NODE_TYPE_TYPEDEF, // ^ + + D3D12_HLSL_NODE_TYPE_STRUCT, // has Variables as member like buffers do, + // localId is the typeId (if not fwd decl) + D3D12_HLSL_NODE_TYPE_UNION, // ^ + + D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE, + + D3D12_HLSL_NODE_TYPE_INTERFACE, + D3D12_HLSL_NODE_TYPE_PARAMETER, + + // Control flow (Stmts), for full inspection of what variables exist where and + // scopes + + D3D12_HLSL_NODE_TYPE_IF, + D3D12_HLSL_NODE_TYPE_SCOPE, + D3D12_HLSL_NODE_TYPE_DO, + D3D12_HLSL_NODE_TYPE_SWITCH, + D3D12_HLSL_NODE_TYPE_WHILE, + D3D12_HLSL_NODE_TYPE_FOR, + + D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE, + + // TODO: D3D12_HLSL_NODE_TYPE_USING, + + D3D12_HLSL_NODE_TYPE_RESERVED = + 1 << 7, // Highest bit; reserved as an indicator for fwd declarations + + D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, + + // Don't forget to properly update NodeTypeToString + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE +}; + +struct D3D12_HLSL_NODE { + LPCSTR Name; + LPCSTR Semantic; + D3D12_HLSL_NODE_TYPE Type; + UINT LocalId; + UINT ChildCount; + UINT Parent; + UINT AnnotationCount; + UINT FwdBckDeclareNode; //If UINT_MAX has no forward / backward declare + BOOL IsFwdDeclare; +}; + +struct D3D12_HLSL_NODE_SYMBOL { + LPCSTR FileName; + UINT LineId; + UINT LineCount; + UINT ColumnStart; + UINT ColumnEnd; +}; + +// TODO: Move to d3d12shader.h + +struct D3D12_ARRAY_DESC { + UINT ArrayDims; + UINT ArrayLengths[32]; // SPV_REFLECT_MAX_ARRAY_DIMS +}; + +struct D3D12_SHADER_INPUT_BIND_DESC1 { + D3D12_SHADER_INPUT_BIND_DESC Desc; + D3D12_ARRAY_DESC ArrayInfo; +}; + +typedef struct _D3D12_SHADER_TYPE_DESC1 { + D3D12_SHADER_TYPE_DESC Desc; + LPCSTR DisplayName; // Display name (not underlying name) + UINT DisplayElements; +} D3D12_SHADER_TYPE_DESC1; + +DECLARE_INTERFACE_(ID3D12ShaderReflectionType1, ID3D12ShaderReflectionType) { + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_TYPE_DESC1 *pDesc) PURE; + STDMETHOD(GetArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) PURE; + STDMETHOD(GetDisplayArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) PURE; +}; + +typedef interface IDxcHLSLReflection IDxcHLSLReflection; + +// {7016F834-AE85-4C86-A473-8C2C981DD370} +interface DECLSPEC_UUID("7016f834-ae85-4c86-a473-8c2c981dd370") + IDxcHLSLReflection; +DEFINE_GUID(IID_IDxcHLSLReflection, 0x7016f834, 0xae85, 0x4c86, 0xa4, 0x73, 0x8c, + 0x2c, 0x98, 0x1d, 0xd3, 0x70); + +#undef INTERFACE +#define INTERFACE IDxcHLSLReflection + +DECLARE_INTERFACE(IDxcHLSLReflection) { + + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_HLSL_REFLECTION_DESC *pDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex) + (THIS_ _In_ UINT Index) PURE; + + // The D3D12_SHADER_INPUT_BIND_DESC permits providing invalid Space and + // BindPoint. In the future, implementations could decide to return this + // depending on the backend. But since this is HLSL frontend reflection, we don't + // know the bindings on the backend. + + STDMETHOD(GetResourceBindingDesc) + (THIS_ _In_ UINT ResourceIndex, _Out_ D3D12_SHADER_INPUT_BIND_DESC1 *pDesc) + PURE; + + STDMETHOD(GetFunctionDesc) + (THIS_ _In_ UINT FunctionIndex, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) + PURE; + + // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. + STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) + (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE; + + STDMETHOD(GetStructTypeByIndex) + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) + PURE; + + STDMETHOD(GetUnionTypeByIndex) + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) + PURE; + + STDMETHOD(GetInterfaceTypeByIndex) + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) + PURE; + + STDMETHOD(GetTypeByIndex) + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) + PURE; + + STDMETHOD(GetEnumDesc) + (THIS_ _In_ UINT EnumIndex, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; + + STDMETHOD(GetEnumValueByIndex) + (THIS_ _In_ UINT EnumIndex, _In_ UINT ValueIndex, + _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) PURE; + + STDMETHOD(GetAnnotationByIndex) + (THIS_ _In_ UINT NodeId, _In_ UINT Index, + _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) PURE; + + STDMETHOD(GetNodeDesc) + (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE *pDesc) PURE; + + STDMETHOD(GetChildNode) + (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, + _Out_ UINT *pChildNodeId) PURE; + + STDMETHOD(GetChildDesc) + (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, + _Out_ D3D12_HLSL_NODE *pDesc) PURE; + + // Only available if symbols aren't stripped + + STDMETHOD(GetNodeSymbolDesc) + (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE_SYMBOL *pSymbol) PURE; + + // Name helpers + + STDMETHOD(GetNodeByName) + (THIS_ _In_ LPCSTR Name, _Out_ UINT *pNodeId) PURE; + + STDMETHOD(GetNodeSymbolDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE_SYMBOL *pSymbol) PURE; + + STDMETHOD(GetNodeDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE *pDesc) PURE; + + STDMETHOD(GetAnnotationByIndexAndName) + (THIS_ _In_ LPCSTR Name, _In_ UINT Index, + _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) PURE; + + STDMETHOD(GetEnumDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; + + STDMETHOD(GetEnumValueByNameAndIndex) + (THIS_ _In_ LPCSTR Name, _In_ UINT ValueIndex, + _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) PURE; + + STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByName) + (THIS_ _In_ LPCSTR Name) PURE; + + STDMETHOD(GetFunctionDescByName) + (THIS_ _In_ LPCSTR Name, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) PURE; + + STDMETHOD(GetResourceBindingDescByName) + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_SHADER_INPUT_BIND_DESC1 * pDesc) PURE; + + STDMETHOD(GetStructTypeByName) + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + + STDMETHOD(GetUnionTypeByName) + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + + STDMETHOD(GetInterfaceTypeByName) + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; +}; + +#undef INTERFACE + +CLSID_SCOPE const CLSID + CLSID_DxcReflector = {/* ba5a8d8e-bf71-435a-977f-1677d7bcccc1 */ + 0xba5a8d8e, + 0xbf71, + 0x435a, + {0x16, 0x77, 0xd7, 0xbc, 0xcc, 0xc1}}; + +CROSS_PLATFORM_UUIDOF(IDxcHLSLReflector, "ba5a8d8e-bf71-435a-977f-1677d7bcccc1") +struct IDxcHLSLReflector : public IUnknown { + + virtual HRESULT STDMETHODCALLTYPE FromSource( + IDxcBlobEncoding *pSource, + // Optional file name for pSource. Used in errors and include handlers. + LPCWSTR pSourceName, + // Compiler arguments + LPCWSTR *pArguments, UINT32 argCount, + // Defines + DxcDefine *pDefines, UINT32 defineCount, + // user-provided interface to handle #include directives (optional) + IDxcIncludeHandler *pIncludeHandler, + IDxcOperationResult **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE + FromBlob(IDxcBlob *data, IDxcHLSLReflection **ppReflection) = 0; + + virtual HRESULT STDMETHODCALLTYPE ToBlob(IDxcHLSLReflection *reflection, + IDxcBlob **ppResult) = 0; +}; + +#endif diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index f2acaef134..53685a66c1 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -71,335 +71,4 @@ struct IDxcRewriter2 : public IDxcRewriter { IDxcIncludeHandler *pIncludeHandler, IDxcOperationResult **ppResult) = 0; }; -//Expose HLSL reflection before DXIL/SPIRV generation. -//(Ran after the preprocessed HLSL is obtained). -//This is useful to avoid custom parsers from reinventing the wheel. -//You could use it to find all entrypoints even if [shader("")] isn't used, -//Find struct/enum information, find out about optimized out registers, etc. - -enum D3D12_HLSL_REFLECTION_FEATURE { - - D3D12_HLSL_REFLECTION_FEATURE_NONE = 0, - - // Includes cbuffer and registers only - D3D12_HLSL_REFLECTION_FEATURE_BASICS = 1 << 0, - - D3D12_HLSL_REFLECTION_FEATURE_FUNCTIONS = 1 << 1, - D3D12_HLSL_REFLECTION_FEATURE_NAMESPACES = 1 << 2, - - // Include user types (struct, enum, typedef, etc.) - D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES = 1 << 3, - - // Variables, structs, functions defined in functions - D3D12_HLSL_REFLECTION_FEATURE_SCOPES = 1 << 4, - - // Symbol info (stripping this will remove names and file location info) - D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO = 1 << 16, - - D3D12_HLSL_REFLECTION_FEATURE_ALL = D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - 1 -}; - -inline D3D12_HLSL_REFLECTION_FEATURE &operator|=(D3D12_HLSL_REFLECTION_FEATURE &a, - D3D12_HLSL_REFLECTION_FEATURE b) { - return a = (D3D12_HLSL_REFLECTION_FEATURE)(uint32_t(a) | uint32_t(b)); -} - -inline D3D12_HLSL_REFLECTION_FEATURE & -operator&=(D3D12_HLSL_REFLECTION_FEATURE &a, - D3D12_HLSL_REFLECTION_FEATURE b) { - return a = (D3D12_HLSL_REFLECTION_FEATURE)(uint32_t(a) & uint32_t(b)); -} - -inline D3D12_HLSL_REFLECTION_FEATURE -operator~(D3D12_HLSL_REFLECTION_FEATURE a) { - return (D3D12_HLSL_REFLECTION_FEATURE) ~uint32_t(a); -} - -struct D3D12_HLSL_REFLECTION_DESC { - D3D12_HLSL_REFLECTION_FEATURE Features; - UINT ConstantBufferCount; - UINT ResourceCount; - UINT FunctionCount; - UINT EnumCount; - UINT NodeCount; - UINT TypeCount; - UINT StructCount; - UINT UnionCount; - UINT InterfaceCount; -}; - -struct D3D12_HLSL_FUNCTION_DESC { - LPCSTR Name; // Function name - UINT FunctionParameterCount; // Number of logical parameters in the function - // signature (not including return) - BOOL HasReturn; // TRUE, if function returns a value, false - it is a - // subroutine -}; - -enum D3D12_HLSL_ENUM_TYPE { - - D3D12_HLSL_ENUM_TYPE_UINT, - D3D12_HLSL_ENUM_TYPE_INT, - D3D12_HLSL_ENUM_TYPE_UINT64_T, - D3D12_HLSL_ENUM_TYPE_INT64_T, - D3D12_HLSL_ENUM_TYPE_UINT16_T, - D3D12_HLSL_ENUM_TYPE_INT16_T, - - D3D12_HLSL_ENUM_TYPE_START = D3D12_HLSL_ENUM_TYPE_UINT, - D3D12_HLSL_ENUM_TYPE_END = D3D12_HLSL_ENUM_TYPE_INT16_T -}; - -struct D3D12_HLSL_ENUM_DESC { - LPCSTR Name; - UINT ValueCount; - D3D12_HLSL_ENUM_TYPE Type; -}; - -struct D3D12_HLSL_ENUM_VALUE { - LPCSTR Name; - INT64 Value; -}; - -struct D3D12_HLSL_ANNOTATION { - LPCSTR Name; - BOOL IsBuiltin; -}; - -enum D3D12_HLSL_NODE_TYPE { - - D3D12_HLSL_NODE_TYPE_REGISTER, - D3D12_HLSL_NODE_TYPE_FUNCTION, - D3D12_HLSL_NODE_TYPE_ENUM, - D3D12_HLSL_NODE_TYPE_ENUM_VALUE, - D3D12_HLSL_NODE_TYPE_NAMESPACE, - - D3D12_HLSL_NODE_TYPE_VARIABLE, // localId points to the type - D3D12_HLSL_NODE_TYPE_TYPEDEF, // ^ - - D3D12_HLSL_NODE_TYPE_STRUCT, // has Variables as member like buffers do, - // localId is the typeId (if not fwd decl) - D3D12_HLSL_NODE_TYPE_UNION, // ^ - - D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE, - - D3D12_HLSL_NODE_TYPE_INTERFACE, - D3D12_HLSL_NODE_TYPE_PARAMETER, - - // Control flow (Stmts), for full inspection of what variables exist where and - // scopes - - D3D12_HLSL_NODE_TYPE_IF, - D3D12_HLSL_NODE_TYPE_SCOPE, - D3D12_HLSL_NODE_TYPE_DO, - D3D12_HLSL_NODE_TYPE_SWITCH, - D3D12_HLSL_NODE_TYPE_WHILE, - D3D12_HLSL_NODE_TYPE_FOR, - - D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE, - - // TODO: D3D12_HLSL_NODE_TYPE_USING, - - D3D12_HLSL_NODE_TYPE_RESERVED = - 1 << 7, // Highest bit; reserved as an indicator for fwd declarations - - D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, - - // Don't forget to properly update NodeTypeToString - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE -}; - -struct D3D12_HLSL_NODE { - LPCSTR Name; - LPCSTR Semantic; - D3D12_HLSL_NODE_TYPE Type; - UINT LocalId; - UINT ChildCount; - UINT Parent; - UINT AnnotationCount; - UINT FwdBckDeclareNode; //If UINT_MAX has no forward / backward declare - BOOL IsFwdDeclare; -}; - -struct D3D12_HLSL_NODE_SYMBOL { - LPCSTR FileName; - UINT LineId; - UINT LineCount; - UINT ColumnStart; - UINT ColumnEnd; -}; - -// TODO: Move to d3d12shader.h - -struct D3D12_ARRAY_DESC { - UINT ArrayDims; - UINT ArrayLengths[32]; // SPV_REFLECT_MAX_ARRAY_DIMS -}; - -struct D3D12_SHADER_INPUT_BIND_DESC1 { - D3D12_SHADER_INPUT_BIND_DESC Desc; - D3D12_ARRAY_DESC ArrayInfo; -}; - -typedef struct _D3D12_SHADER_TYPE_DESC1 { - D3D12_SHADER_TYPE_DESC Desc; - LPCSTR DisplayName; // Display name (not underlying name) - UINT DisplayElements; -} D3D12_SHADER_TYPE_DESC1; - -DECLARE_INTERFACE_(ID3D12ShaderReflectionType1, ID3D12ShaderReflectionType) { - STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_TYPE_DESC1 *pDesc) PURE; - STDMETHOD(GetArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) PURE; - STDMETHOD(GetDisplayArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) PURE; -}; - -typedef interface IDxcHLSLReflection IDxcHLSLReflection; - -// {7016F834-AE85-4C86-A473-8C2C981DD370} -interface DECLSPEC_UUID("7016f834-ae85-4c86-a473-8c2c981dd370") - IDxcHLSLReflection; -DEFINE_GUID(IID_IDxcHLSLReflection, 0x7016f834, 0xae85, 0x4c86, 0xa4, 0x73, 0x8c, - 0x2c, 0x98, 0x1d, 0xd3, 0x70); - -#undef INTERFACE -#define INTERFACE IDxcHLSLReflection - -DECLARE_INTERFACE(IDxcHLSLReflection) { - - STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_HLSL_REFLECTION_DESC *pDesc) PURE; - - STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex) - (THIS_ _In_ UINT Index) PURE; - - // The D3D12_SHADER_INPUT_BIND_DESC permits providing invalid Space and - // BindPoint. In the future, implementations could decide to return this - // depending on the backend. But since this is HLSL frontend reflection, we don't - // know the bindings on the backend. - - STDMETHOD(GetResourceBindingDesc) - (THIS_ _In_ UINT ResourceIndex, _Out_ D3D12_SHADER_INPUT_BIND_DESC1 *pDesc) - PURE; - - STDMETHOD(GetFunctionDesc) - (THIS_ _In_ UINT FunctionIndex, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) - PURE; - - // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. - STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter) - (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE; - - STDMETHOD(GetStructTypeByIndex) - (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) - PURE; - - STDMETHOD(GetUnionTypeByIndex) - (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) - PURE; - - STDMETHOD(GetInterfaceTypeByIndex) - (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) - PURE; - - STDMETHOD(GetTypeByIndex) - (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) - PURE; - - STDMETHOD(GetEnumDesc) - (THIS_ _In_ UINT EnumIndex, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; - - STDMETHOD(GetEnumValueByIndex) - (THIS_ _In_ UINT EnumIndex, _In_ UINT ValueIndex, - _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) PURE; - - STDMETHOD(GetAnnotationByIndex) - (THIS_ _In_ UINT NodeId, _In_ UINT Index, - _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) PURE; - - STDMETHOD(GetNodeDesc) - (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE *pDesc) PURE; - - STDMETHOD(GetChildNode) - (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, - _Out_ UINT *pChildNodeId) PURE; - - STDMETHOD(GetChildDesc) - (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, - _Out_ D3D12_HLSL_NODE *pDesc) PURE; - - // Only available if symbols aren't stripped - - STDMETHOD(GetNodeSymbolDesc) - (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE_SYMBOL *pSymbol) PURE; - - // Name helpers - - STDMETHOD(GetNodeByName) - (THIS_ _In_ LPCSTR Name, _Out_ UINT *pNodeId) PURE; - - STDMETHOD(GetNodeSymbolDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE_SYMBOL *pSymbol) PURE; - - STDMETHOD(GetNodeDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE *pDesc) PURE; - - STDMETHOD(GetAnnotationByIndexAndName) - (THIS_ _In_ LPCSTR Name, _In_ UINT Index, - _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) PURE; - - STDMETHOD(GetEnumDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; - - STDMETHOD(GetEnumValueByNameAndIndex) - (THIS_ _In_ LPCSTR Name, _In_ UINT ValueIndex, - _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) PURE; - - STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByName) - (THIS_ _In_ LPCSTR Name) PURE; - - STDMETHOD(GetFunctionDescByName) - (THIS_ _In_ LPCSTR Name, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) PURE; - - STDMETHOD(GetResourceBindingDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_SHADER_INPUT_BIND_DESC1 * pDesc) PURE; - - STDMETHOD(GetStructTypeByName) - (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; - - STDMETHOD(GetUnionTypeByName) - (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; - - STDMETHOD(GetInterfaceTypeByName) - (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; -}; - -#undef INTERFACE - -CLSID_SCOPE const CLSID - CLSID_DxcReflector = {/* ba5a8d8e-bf71-435a-977f-1677d7bcccc1 */ - 0xba5a8d8e, - 0xbf71, - 0x435a, - {0x16, 0x77, 0xd7, 0xbc, 0xcc, 0xc1}}; - -CROSS_PLATFORM_UUIDOF(IDxcHLSLReflector, "ba5a8d8e-bf71-435a-977f-1677d7bcccc1") -struct IDxcHLSLReflector : public IUnknown { - - virtual HRESULT STDMETHODCALLTYPE FromSource( - IDxcBlobEncoding *pSource, - // Optional file name for pSource. Used in errors and include handlers. - LPCWSTR pSourceName, - // Compiler arguments - LPCWSTR *pArguments, UINT32 argCount, - // Defines - DxcDefine *pDefines, UINT32 defineCount, - // user-provided interface to handle #include directives (optional) - IDxcIncludeHandler *pIncludeHandler, - IDxcOperationResult **ppResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE - FromBlob(IDxcBlob *data, IDxcHLSLReflection **ppReflection) = 0; - - virtual HRESULT STDMETHODCALLTYPE ToBlob(IDxcHLSLReflection *reflection, - IDxcBlob **ppResult) = 0; -}; - #endif diff --git a/tools/clang/tools/dxcompiler/dxcapi.cpp b/tools/clang/tools/dxcompiler/dxcapi.cpp index 703b202025..e298ed8494 100644 --- a/tools/clang/tools/dxcompiler/dxcapi.cpp +++ b/tools/clang/tools/dxcompiler/dxcapi.cpp @@ -21,6 +21,7 @@ #include "dxc/config.h" #include "dxc/dxcisense.h" #include "dxc/dxctools.h" +#include "dxc/dxcreflect.h" #ifdef _WIN32 #include "dxcetw.h" #endif diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index f8d91224c0..bda4f323a0 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -41,7 +41,7 @@ #include "dxc/Support/dxcapi.impl.h" #include "dxc/Support/dxcfilesystem.h" #include "dxc/dxcapi.internal.h" -#include "dxc/dxctools.h" +#include "dxc/dxcreflect.h" #include "dxc/DxcReflection/DxcReflection.h" diff --git a/tools/clang/tools/dxreflector/dxreflector.cpp b/tools/clang/tools/dxreflector/dxreflector.cpp index 0ca93d1eaf..df4628dc0d 100644 --- a/tools/clang/tools/dxreflector/dxreflector.cpp +++ b/tools/clang/tools/dxreflector/dxreflector.cpp @@ -22,7 +22,7 @@ #include "dxc/Support/WinFunctions.h" #include "dxc/Support/dxcapi.use.h" #include "dxc/dxcapi.h" -#include "dxc/dxctools.h" +#include "dxc/dxcreflect.h" #include "llvm/Support/raw_ostream.h" inline bool wcsieq(LPCWSTR a, LPCWSTR b) { return _wcsicmp(a, b) == 0; } From a2c86c4c1ea77e324dd58df42a63c33bd6547d08 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 3 Nov 2025 23:42:16 +0100 Subject: [PATCH 083/126] Added defaulting lib version to dxcreflector --- .../tools/dxcreflection/dxcreflector.cpp | 2 + tools/clang/tools/dxreflector/dxreflector.cpp | 39 ++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index bda4f323a0..666f989a1b 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -1436,6 +1436,7 @@ void SetupCompilerCommon(CompilerInstance &compiler, compiler.getLangOpts().UseMinPrecision = !opts.Enable16BitTypes; compiler.getDiagnostics().setIgnoreAllWarnings(!opts.OutputWarnings); compiler.getCodeGenOpts().MainFileName = pMainFile; + compiler.getLangOpts().HLSLProfile = compiler.getCodeGenOpts().HLSLProfile = opts.TargetProfile; @@ -1737,6 +1738,7 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { hlsl::options::MainArgs mainArgs(argCount, pArguments, 0); hlsl::options::DxcOpts opts; + IFR(ReadOptsAndValidate(mainArgs, opts, ppResult)); HRESULT hr; if (*ppResult && SUCCEEDED((*ppResult)->GetStatus(&hr)) && FAILED(hr)) { diff --git a/tools/clang/tools/dxreflector/dxreflector.cpp b/tools/clang/tools/dxreflector/dxreflector.cpp index df4628dc0d..fe63647116 100644 --- a/tools/clang/tools/dxreflector/dxreflector.cpp +++ b/tools/clang/tools/dxreflector/dxreflector.cpp @@ -25,6 +25,8 @@ #include "dxc/dxcreflect.h" #include "llvm/Support/raw_ostream.h" +#include "dxc/DXIL/DxilShaderModel.h" + inline bool wcsieq(LPCWSTR a, LPCWSTR b) { return _wcsicmp(a, b) == 0; } using namespace dxc; @@ -56,6 +58,39 @@ int main(int argc, const char **argv) { { std::string errorString; llvm::raw_string_ostream errorStream(errorString); + + // Target profile is used to detect for example if 16-bit types are allowed. + // This is the only way to correct the missing target. + + { + unsigned missingArgIndex = 0, missingArgCount = 0; + InputArgList Args = + optionTable->ParseArgs(argStrings.getArrayRef(), missingArgIndex, + missingArgCount, DxreflectorFlags); + + if (!Args.hasArg(OPT_target_profile)) { + + const hlsl::ShaderModel *SM = hlsl::ShaderModel::Get( + hlsl::DXIL::ShaderKind::Library, hlsl::ShaderModel::kHighestMajor, + hlsl::ShaderModel::kHighestMinor); + + if (SM && SM->IsValid()) { + + dxreflectorOpts.TargetProfile = SM->GetName(); + + argStrings.Utf8StringVector.push_back("-T"); + argStrings.Utf8StringVector.push_back(SM->GetName()); + + argStrings.Utf8CharPtrVector.resize( + argStrings.Utf8CharPtrVector.size() + 2); + + for (int i = 0; i < argStrings.Utf8StringVector.size(); ++i) + argStrings.Utf8CharPtrVector[i] = + argStrings.Utf8StringVector[i].c_str(); + } + } + } + int optResult = ReadDxcOpts(optionTable, DxreflectorFlags, argStrings, dxreflectorOpts, errorStream); errorStream.flush(); @@ -137,7 +172,9 @@ int main(int argc, const char **argv) { IFT(pLibrary->CreateIncludeHandler(&pIncludeHandler)); IFT(dxcSupport.CreateInstance(CLSID_DxcReflector, &pReflector)); - IFT(pReflector->FromSource(pSource, wName.c_str(), argv_, argc, + IFT(pReflector->FromSource(pSource, wName.c_str(), + (LPCWSTR*)argStrings.Utf8CharPtrVector.data(), + uint32_t(argStrings.Utf8CharPtrVector.size()), nullptr, 0, pIncludeHandler, &pRewriteResult)); From 58df8385d8be9f9ef8280c54db63cb20165b514a Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 8 Nov 2025 23:26:57 +0100 Subject: [PATCH 084/126] Reset stale changes --- include/dxc/DXIL/DxilModule.h | 3 -- include/dxc/HLSL/HLModule.h | 2 - include/dxc/Support/HLSLOptions.h | 21 ++++---- include/dxc/Support/HLSLOptions.td | 3 -- include/dxc/config.h | 4 -- include/dxc/dxctools.h | 1 - lib/DXIL/DxilModule.cpp | 10 ---- lib/DxcSupport/HLSLOptions.cpp | 4 -- lib/HLSL/DxilCondenseResources.cpp | 6 +-- lib/HLSL/DxilGenerationPass.cpp | 1 - lib/HLSL/HLModule.cpp | 18 +++---- tools/clang/include/clang/AST/HlslTypes.h | 1 - .../include/clang/Frontend/CodeGenOptions.h | 2 - tools/clang/lib/AST/HlslTypes.cpp | 8 --- tools/clang/lib/CodeGen/CGHLSLMS.cpp | 2 - .../consistent_bindings_gold.hlsl | 49 ------------------- .../clang/tools/dxcompiler/dxcompilerobj.cpp | 2 - tools/clang/tools/dxreflector/dxreflector.cpp | 5 +- .../clang/tools/libclang/dxcrewriteunused.cpp | 3 -- tools/clang/unittests/HLSL/RewriterTest.cpp | 28 +++++------ 20 files changed, 32 insertions(+), 141 deletions(-) delete mode 100644 include/dxc/config.h delete mode 100644 tools/clang/test/HLSL/rewriter/correct_rewrites/consistent_bindings_gold.hlsl diff --git a/include/dxc/DXIL/DxilModule.h b/include/dxc/DXIL/DxilModule.h index 5a91f0b204..3f1ba12f86 100644 --- a/include/dxc/DXIL/DxilModule.h +++ b/include/dxc/DXIL/DxilModule.h @@ -287,8 +287,6 @@ class DxilModule { // Intermediate options that do not make it to DXIL void SetLegacyResourceReservation(bool legacyResourceReservation); bool GetLegacyResourceReservation() const; - void SetConsistentBindings(bool consistentBindings); - bool GetConsistentBindings() const; void ClearIntermediateOptions(); // Hull and Domain shaders. @@ -348,7 +346,6 @@ class DxilModule { enum IntermediateFlags : uint32_t { LegacyResourceReservation = 1 << 0, - ConsistentBindings = 1 << 1 }; llvm::LLVMContext &m_Ctx; diff --git a/include/dxc/HLSL/HLModule.h b/include/dxc/HLSL/HLModule.h index 90d0c218cd..653fc967d5 100644 --- a/include/dxc/HLSL/HLModule.h +++ b/include/dxc/HLSL/HLModule.h @@ -54,7 +54,6 @@ struct HLOptions { bDisableOptimizations(false), PackingStrategy(0), bUseMinPrecision(false), bDX9CompatMode(false), bFXCCompatMode(false), bLegacyResourceReservation(false), bForceZeroStoreLifetimes(false), - bConsistentBindings(false), unused(0) {} uint32_t GetHLOptionsRaw() const; void SetHLOptionsRaw(uint32_t data); @@ -71,7 +70,6 @@ struct HLOptions { unsigned bLegacyResourceReservation : 1; unsigned bForceZeroStoreLifetimes : 1; unsigned bResMayAlias : 1; - unsigned bConsistentBindings : 1; unsigned unused : 19; }; diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index d81807536c..5d51aaf534 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -106,16 +106,16 @@ class DxcDefines { }; struct RewriterOpts { - bool Unchanged = false; // OPT_rw_unchanged - bool SkipFunctionBody = false; // OPT_rw_skip_function_body - bool SkipStatic = false; // OPT_rw_skip_static - bool GlobalExternByDefault = false; // OPT_rw_global_extern_by_default - bool KeepUserMacro = false; // OPT_rw_keep_user_macro - bool ExtractEntryUniforms = false; // OPT_rw_extract_entry_uniforms - bool RemoveUnusedGlobals = false; // OPT_rw_remove_unused_globals - bool RemoveUnusedFunctions = false; // OPT_rw_remove_unused_functions - bool WithLineDirective = false; // OPT_rw_line_directive - bool DeclGlobalCB = false; // OPT_rw_decl_global_cb + bool Unchanged = false; // OPT_rw_unchanged + bool SkipFunctionBody = false; // OPT_rw_skip_function_body + bool SkipStatic = false; // OPT_rw_skip_static + bool GlobalExternByDefault = false; // OPT_rw_global_extern_by_default + bool KeepUserMacro = false; // OPT_rw_keep_user_macro + bool ExtractEntryUniforms = false; // OPT_rw_extract_entry_uniforms + bool RemoveUnusedGlobals = false; // OPT_rw_remove_unused_globals + bool RemoveUnusedFunctions = false; // OPT_rw_remove_unused_functions + bool WithLineDirective = false; // OPT_rw_line_directive + bool DeclGlobalCB = false; // OPT_rw_decl_global_cb }; struct ReflectOpts { @@ -240,7 +240,6 @@ class DxcOpts { std::string TimeTrace = ""; // OPT_ftime_trace[EQ] unsigned TimeTraceGranularity = 500; // OPT_ftime_trace_granularity_EQ bool VerifyDiagnostics = false; // OPT_verify - bool ConsistentBindings = false; // OPT_consistent_bindings bool Verbose = false; // OPT_verbose // Optimization pass enables, disables and selects diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index 5c7338f1fc..69dd43730b 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -580,9 +580,6 @@ def getprivate : JoinedOrSeparate<["-", "/"], "getprivate">, Flags<[DriverOption def nologo : Flag<["-", "/"], "nologo">, Group, Flags<[DriverOption, HelpHidden]>, HelpText<"Suppress copyright message">; -def consistent_bindings : Flag<["-", "/"], "consistent-bindings">, Group, Flags<[CoreOption]>, - HelpText<"Generate bindings for registers with no pre-declared binding (consistently regardless of optimization).">; - ////////////////////////////////////////////////////////////////////////////// // Reflector Options diff --git a/include/dxc/config.h b/include/dxc/config.h deleted file mode 100644 index c7dce25e33..0000000000 --- a/include/dxc/config.h +++ /dev/null @@ -1,4 +0,0 @@ -/* Disable overriding memory allocators. */ -/* #undef DXC_DISABLE_ALLOCATOR_OVERRIDES */ -/* Generate a trap if an hlsl::Exception is thrown during code generation */ -/* #undef DXC_CODEGEN_EXCEPTIONS_TRAP */ diff --git a/include/dxc/dxctools.h b/include/dxc/dxctools.h index 53685a66c1..bfdc0d86f7 100644 --- a/include/dxc/dxctools.h +++ b/include/dxc/dxctools.h @@ -13,7 +13,6 @@ #define __DXC_TOOLS__ #include -#include "d3d12shader.h" enum RewriterOptionMask { Default = 0, diff --git a/lib/DXIL/DxilModule.cpp b/lib/DXIL/DxilModule.cpp index d55923d964..f4abdd15aa 100644 --- a/lib/DXIL/DxilModule.cpp +++ b/lib/DXIL/DxilModule.cpp @@ -586,16 +586,6 @@ bool DxilModule::GetLegacyResourceReservation() const { return (m_IntermediateFlags & LegacyResourceReservation) != 0; } -void DxilModule::SetConsistentBindings(bool consistentBindings) { - m_IntermediateFlags &= ~ConsistentBindings; - if (consistentBindings) - m_IntermediateFlags |= ConsistentBindings; -} - -bool DxilModule::GetConsistentBindings() const { - return (m_IntermediateFlags & ConsistentBindings) != 0; -} - void DxilModule::ClearIntermediateOptions() { m_IntermediateFlags = 0; } unsigned DxilModule::GetInputControlPointCount() const { diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index 492c060146..0b3e4c95ea 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -865,10 +865,6 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, opts.TimeReport = Args.hasFlag(OPT_ftime_report, OPT_INVALID, false); opts.TimeTrace = Args.hasFlag(OPT_ftime_trace, OPT_INVALID, false) ? "-" : ""; opts.VerifyDiagnostics = Args.hasFlag(OPT_verify, OPT_INVALID, false); - - opts.ConsistentBindings = - Args.hasFlag(OPT_consistent_bindings, OPT_INVALID, false); - opts.Verbose = Args.hasFlag(OPT_verbose, OPT_INVALID, false); if (Args.hasArg(OPT_ftime_trace_EQ)) opts.TimeTrace = Args.getLastArgValue(OPT_ftime_trace_EQ); diff --git a/lib/HLSL/DxilCondenseResources.cpp b/lib/HLSL/DxilCondenseResources.cpp index 18dd741cc8..09dd9cea64 100644 --- a/lib/HLSL/DxilCondenseResources.cpp +++ b/lib/HLSL/DxilCondenseResources.cpp @@ -550,8 +550,7 @@ class DxilLowerCreateHandleForLib : public ModulePass { ResourceRegisterAllocator.GatherReservedRegisters(DM); // Remove unused resources. - if (!DM.GetConsistentBindings()) - DM.RemoveResourcesWithUnusedSymbols(); + DM.RemoveResourcesWithUnusedSymbols(); unsigned newResources = DM.GetCBuffers().size() + DM.GetUAVs().size() + DM.GetSRVs().size() + DM.GetSamplers().size(); @@ -572,9 +571,6 @@ class DxilLowerCreateHandleForLib : public ModulePass { bChanged |= ResourceRegisterAllocator.AllocateRegisters(DM); - if (DM.GetConsistentBindings()) - DM.RemoveResourcesWithUnusedSymbols(); - // Fill in top-level CBuffer variable usage bit UpdateCBufferUsage(); diff --git a/lib/HLSL/DxilGenerationPass.cpp b/lib/HLSL/DxilGenerationPass.cpp index 1686482518..c3a6ad7dfc 100644 --- a/lib/HLSL/DxilGenerationPass.cpp +++ b/lib/HLSL/DxilGenerationPass.cpp @@ -155,7 +155,6 @@ void InitDxilModuleFromHLModule(HLModule &H, DxilModule &M, bool HasDebugInfo) { // bool m_bDisableOptimizations; M.SetDisableOptimization(H.GetHLOptions().bDisableOptimizations); M.SetLegacyResourceReservation(H.GetHLOptions().bLegacyResourceReservation); - M.SetConsistentBindings(H.GetHLOptions().bConsistentBindings); // bool m_bDisableMathRefactoring; // bool m_bEnableDoublePrecision; // bool m_bEnableDoubleExtensions; diff --git a/lib/HLSL/HLModule.cpp b/lib/HLSL/HLModule.cpp index ce6241a3b6..bab6e23a30 100644 --- a/lib/HLSL/HLModule.cpp +++ b/lib/HLSL/HLModule.cpp @@ -231,18 +231,17 @@ void HLModule::RemoveFunction(llvm::Function *F) { namespace { template bool RemoveResource(std::vector> &vec, - GlobalVariable *pVariable, bool keepAllocated, bool dontUpdateIds) { + GlobalVariable *pVariable, bool keepAllocated) { for (auto p = vec.begin(), e = vec.end(); p != e; ++p) { if ((*p)->GetGlobalSymbol() != pVariable) continue; - if ((keepAllocated && (*p)->IsAllocated()) || dontUpdateIds) { + if (keepAllocated && (*p)->IsAllocated()) { // Keep the resource, but it has no more symbol. (*p)->SetGlobalSymbol(UndefValue::get(pVariable->getType())); } else { // Erase the resource alltogether and update IDs of subsequent ones p = vec.erase(p); - for (e = vec.end(); p != e; ++p) { unsigned ID = (*p)->GetID() - 1; (*p)->SetID(ID); @@ -263,21 +262,16 @@ void HLModule::RemoveGlobal(llvm::GlobalVariable *GV) { // register range from being allocated to other resources. bool keepAllocated = GetHLOptions().bLegacyResourceReservation; - // Consistent bindings are different than -flegacy-resource-reservation; - // We need the IDs to stay the same, but it's fine to remove unused registers. - // It's actually wanted, because that allows us to know what registers are optimized out. - bool consistentBindings = GetHLOptions().bConsistentBindings; - // This could be considerably faster - check variable type to see which // resource type this is rather than scanning all lists, and look for // usage and removal patterns. - if (RemoveResource(m_CBuffers, GV, keepAllocated, consistentBindings)) + if (RemoveResource(m_CBuffers, GV, keepAllocated)) return; - if (RemoveResource(m_SRVs, GV, keepAllocated, consistentBindings)) + if (RemoveResource(m_SRVs, GV, keepAllocated)) return; - if (RemoveResource(m_UAVs, GV, keepAllocated, consistentBindings)) + if (RemoveResource(m_UAVs, GV, keepAllocated)) return; - if (RemoveResource(m_Samplers, GV, keepAllocated, consistentBindings)) + if (RemoveResource(m_Samplers, GV, keepAllocated)) return; // TODO: do m_TGSMVariables and m_StreamOutputs need maintenance? } diff --git a/tools/clang/include/clang/AST/HlslTypes.h b/tools/clang/include/clang/AST/HlslTypes.h index 2caa408b08..43c1effdb8 100644 --- a/tools/clang/include/clang/AST/HlslTypes.h +++ b/tools/clang/include/clang/AST/HlslTypes.h @@ -497,7 +497,6 @@ bool IsHLSLNumericOrAggregateOfNumericType(clang::QualType type); bool IsHLSLCopyableAnnotatableRecord(clang::QualType QT); bool IsHLSLBuiltinRayAttributeStruct(clang::QualType QT); bool IsHLSLAggregateType(clang::QualType type); -hlsl::DXIL::ResourceClass GetHLSLResourceClass(clang::QualType type); clang::QualType GetHLSLResourceResultType(clang::QualType type); clang::QualType GetHLSLNodeIOResultType(clang::ASTContext &astContext, clang::QualType type); diff --git a/tools/clang/include/clang/Frontend/CodeGenOptions.h b/tools/clang/include/clang/Frontend/CodeGenOptions.h index 2fe3d418b9..859cba53da 100644 --- a/tools/clang/include/clang/Frontend/CodeGenOptions.h +++ b/tools/clang/include/clang/Frontend/CodeGenOptions.h @@ -187,8 +187,6 @@ class CodeGenOptions : public CodeGenOptionsBase { bool HLSLOnlyWarnOnUnrollFail = false; /// Whether use legacy resource reservation. bool HLSLLegacyResourceReservation = false; - /// Whether to keep bindings consistent even if optimized out. - bool HLSLConsistentBindings = false; /// Set [branch] on every if. bool HLSLPreferControlFlow = false; /// Set [flatten] on every if. diff --git a/tools/clang/lib/AST/HlslTypes.cpp b/tools/clang/lib/AST/HlslTypes.cpp index 9748e13069..00c18a81a9 100644 --- a/tools/clang/lib/AST/HlslTypes.cpp +++ b/tools/clang/lib/AST/HlslTypes.cpp @@ -524,14 +524,6 @@ bool IsHLSLResourceType(clang::QualType type) { return false; } -hlsl::DXIL::ResourceClass GetHLSLResourceClass(clang::QualType type) { - - if (HLSLResourceAttr *attr = getAttr(type)) - return attr->getResClass(); - - return hlsl::DXIL::ResourceClass::Invalid; -} - bool IsHLSLHitObjectType(QualType type) { return nullptr != getAttr(type); } diff --git a/tools/clang/lib/CodeGen/CGHLSLMS.cpp b/tools/clang/lib/CodeGen/CGHLSLMS.cpp index f5ddb9b0df..6c68381a20 100644 --- a/tools/clang/lib/CodeGen/CGHLSLMS.cpp +++ b/tools/clang/lib/CodeGen/CGHLSLMS.cpp @@ -400,8 +400,6 @@ CGMSHLSLRuntime::CGMSHLSLRuntime(CodeGenModule &CGM) opts.PackingStrategy = CGM.getCodeGenOpts().HLSLSignaturePackingStrategy; opts.bLegacyResourceReservation = CGM.getCodeGenOpts().HLSLLegacyResourceReservation; - opts.bConsistentBindings = - CGM.getCodeGenOpts().HLSLConsistentBindings; opts.bForceZeroStoreLifetimes = CGM.getCodeGenOpts().HLSLForceZeroStoreLifetimes; diff --git a/tools/clang/test/HLSL/rewriter/correct_rewrites/consistent_bindings_gold.hlsl b/tools/clang/test/HLSL/rewriter/correct_rewrites/consistent_bindings_gold.hlsl deleted file mode 100644 index 4c2810e9f4..0000000000 --- a/tools/clang/test/HLSL/rewriter/correct_rewrites/consistent_bindings_gold.hlsl +++ /dev/null @@ -1,49 +0,0 @@ -RWByteAddressBuffer output1 : register(u2); -RWByteAddressBuffer output2 : register(u15); -RWByteAddressBuffer output3 : register(u0); -RWByteAddressBuffer output4 : register(u0, space1); -RWByteAddressBuffer output5 : SEMA : register(u16); -RWByteAddressBuffer output6 : register(u17); -RWByteAddressBuffer output7 : register(u1); -RWByteAddressBuffer output8[12] : register(u3); -RWByteAddressBuffer output9[12] : register(u18); -RWByteAddressBuffer output10[33] : register(u1, space1); -RWByteAddressBuffer output11[33] : register(u33, space2); -RWByteAddressBuffer output12[33] : register(u0, space2); -StructuredBuffer test : register(t1); -ByteAddressBuffer input13 : SEMA : register(t2); -ByteAddressBuffer input14 : register(t15); -ByteAddressBuffer input15 : register(t0); -ByteAddressBuffer input16[12] : register(t3); -ByteAddressBuffer input17[2] : register(t13, space1); -ByteAddressBuffer input18[12] : register(t1, space1); -ByteAddressBuffer input19[3] : register(t15, space1); -ByteAddressBuffer input20 : register(t0, space1); -SamplerState sampler0 : register(s1); -SamplerState sampler1 : register(s2); -SamplerState sampler2 : register(s0); -SamplerState sampler3 : register(s1, space1); -SamplerState sampler4 : register(s0, space1); -cbuffer test : register(b0) { - const float a; -} -; -cbuffer test2 : register(b1) { - const float b; -} -; -cbuffer test3 : register(b0, space1) { - const float c; -} -; -cbuffer test4 : register(b1, space1) { - const float d; -} -; -const float e; -[numthreads(16, 16, 1)] -void main(uint id : SV_DispatchThreadID) { - output2.Store(id * 4, 1); -} - - diff --git a/tools/clang/tools/dxcompiler/dxcompilerobj.cpp b/tools/clang/tools/dxcompiler/dxcompilerobj.cpp index d58fbfe67f..230047b4a8 100644 --- a/tools/clang/tools/dxcompiler/dxcompilerobj.cpp +++ b/tools/clang/tools/dxcompiler/dxcompilerobj.cpp @@ -1595,8 +1595,6 @@ class DxcCompiler : public IDxcCompiler3, compiler.getCodeGenOpts().HLSLAvoidControlFlow = Opts.AvoidFlowControl; compiler.getCodeGenOpts().HLSLLegacyResourceReservation = Opts.LegacyResourceReservation; - compiler.getCodeGenOpts().HLSLConsistentBindings = - Opts.ConsistentBindings; compiler.getCodeGenOpts().HLSLDefines = defines; compiler.getCodeGenOpts().HLSLPreciseOutputs = Opts.PreciseOutputs; compiler.getCodeGenOpts().MainFileName = pMainFile; diff --git a/tools/clang/tools/dxreflector/dxreflector.cpp b/tools/clang/tools/dxreflector/dxreflector.cpp index fe63647116..5825d65a07 100644 --- a/tools/clang/tools/dxreflector/dxreflector.cpp +++ b/tools/clang/tools/dxreflector/dxreflector.cpp @@ -52,7 +52,7 @@ int main(int argc, const char **argv) { const OptTable *optionTable = getHlslOptTable(); MainArgs argStrings(argc, argv_); DxcOpts dxreflectorOpts; - DxcDllSupport dxcSupport; + DXCLibraryDllLoader dxcSupport; // Read options and check errors. { @@ -111,7 +111,8 @@ int main(int argc, const char **argv) { { std::string dllErrorString; llvm::raw_string_ostream dllErrorStream(dllErrorString); - int dllResult = SetupDxcDllSupport(dxreflectorOpts, dxcSupport, dllErrorStream); + int dllResult = + SetupSpecificDllLoader(dxreflectorOpts, dxcSupport, dllErrorStream); dllErrorStream.flush(); if (dllErrorString.size()) { fprintf(stderr, "%s\n", dllErrorString.data()); diff --git a/tools/clang/tools/libclang/dxcrewriteunused.cpp b/tools/clang/tools/libclang/dxcrewriteunused.cpp index 64fa2dde22..c29854077b 100644 --- a/tools/clang/tools/libclang/dxcrewriteunused.cpp +++ b/tools/clang/tools/libclang/dxcrewriteunused.cpp @@ -11,7 +11,6 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/HlslTypes.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" @@ -45,8 +44,6 @@ #include "dxc/dxcapi.internal.h" #include "dxc/dxctools.h" -#include "dxc/DxcReflection/DxcReflection.h" - // From dxcutil.h namespace dxcutil { bool IsAbsoluteOrCurDirRelative(const llvm::Twine &T); diff --git a/tools/clang/unittests/HLSL/RewriterTest.cpp b/tools/clang/unittests/HLSL/RewriterTest.cpp index 27bf909fb1..1d53a733ef 100644 --- a/tools/clang/unittests/HLSL/RewriterTest.cpp +++ b/tools/clang/unittests/HLSL/RewriterTest.cpp @@ -126,19 +126,16 @@ class RewriterTest : public ::testing::Test { ppBlob)); } - VerifyResult CheckVerifies(LPCWSTR path, LPCWSTR goldPath, - const llvm::SmallVector &args = { - L"-HV", L"2016"}) { + VerifyResult CheckVerifies(LPCWSTR path, LPCWSTR goldPath) { CComPtr pRewriter; VERIFY_SUCCEEDED(CreateRewriter(&pRewriter)); - return CheckVerifies(pRewriter, path, goldPath, args); + return CheckVerifies(pRewriter, path, goldPath); } - VerifyResult - CheckVerifies(IDxcRewriter *pRewriter, LPCWSTR path, LPCWSTR goldPath, - const llvm::SmallVector &args = {L"-HV", L"2016"}) { + VerifyResult CheckVerifies(IDxcRewriter *pRewriter, LPCWSTR path, + LPCWSTR goldPath) { CComPtr pRewriteResult; - RewriteCompareGold(path, goldPath, &pRewriteResult, pRewriter, args); + RewriteCompareGold(path, goldPath, &pRewriteResult, pRewriter); VerifyResult toReturn; @@ -168,11 +165,9 @@ class RewriterTest : public ::testing::Test { return S_OK; } - VerifyResult CheckVerifiesHLSL(LPCWSTR name, LPCWSTR goldName, - const llvm::SmallVector &args = { - L"-HV", L"2016"}) { + VerifyResult CheckVerifiesHLSL(LPCWSTR name, LPCWSTR goldName) { return CheckVerifies(GetPathToHlslDataFile(name).c_str(), - GetPathToHlslDataFile(goldName).c_str(), args); + GetPathToHlslDataFile(goldName).c_str()); } struct FileWithBlob { @@ -215,8 +210,7 @@ class RewriterTest : public ::testing::Test { void RewriteCompareGold(LPCWSTR path, LPCWSTR goldPath, IDxcOperationResult **ppResult, - IDxcRewriter *rewriter, - const llvm::SmallVector &args = {}) { + IDxcRewriter *rewriter) { // Get the source text from a file FileWithBlob source(m_dllSupport, path); @@ -224,12 +218,14 @@ class RewriterTest : public ::testing::Test { DxcDefine myDefines[myDefinesCount] = { {L"myDefine", L"2"}, {L"myDefine3", L"1994"}, {L"myDefine4", nullptr}}; + LPCWSTR args[] = {L"-HV", L"2016"}; + CComPtr rewriter2; VERIFY_SUCCEEDED(rewriter->QueryInterface(&rewriter2)); // Run rewrite unchanged on the source code VERIFY_SUCCEEDED(rewriter2->RewriteWithOptions( - source.BlobEncoding, path, (LPCWSTR *)args.data(), - (uint32_t)args.size(), myDefines, myDefinesCount, nullptr, ppResult)); + source.BlobEncoding, path, args, _countof(args), myDefines, + myDefinesCount, nullptr, ppResult)); // check for compilation errors HRESULT hrStatus; From ecd0095d293ea15c7b7bf7590b814768f359ea84 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sat, 8 Nov 2025 23:43:18 +0100 Subject: [PATCH 085/126] Renamed DxcReflection.cpp to DxcReflectionContainer.h and DxcReflection.h to DxcReflectionContainer.h to avoid conflicts --- .../DxcReflection/{DxcReflection.h => DxcReflectionContainer.h} | 0 tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp | 2 +- tools/clang/tools/dxcreflection/dxcreflector.cpp | 2 +- .../{DxcReflection.cpp => DxcReflectionContainer.cpp} | 2 +- tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename include/dxc/DxcReflection/{DxcReflection.h => DxcReflectionContainer.h} (100%) rename tools/clang/tools/dxcreflectioncontainer/{DxcReflection.cpp => DxcReflectionContainer.cpp} (99%) diff --git a/include/dxc/DxcReflection/DxcReflection.h b/include/dxc/DxcReflection/DxcReflectionContainer.h similarity index 100% rename from include/dxc/DxcReflection/DxcReflection.h rename to include/dxc/DxcReflection/DxcReflectionContainer.h diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 0e741dc465..095658a961 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -18,7 +18,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/basic/SourceManager.h" #include "clang/Lex/Lexer.h" -#include "dxc/DxcReflection/DxcReflection.h" +#include "dxc/DxcReflection/DxcReflectionContainer.h" using namespace clang; diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 666f989a1b..6fd07f694a 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -43,7 +43,7 @@ #include "dxc/dxcapi.internal.h" #include "dxc/dxcreflect.h" -#include "dxc/DxcReflection/DxcReflection.h" +#include "dxc/DxcReflection/DxcReflectionContainer.h" using namespace llvm; using namespace clang; diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflection.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp similarity index 99% rename from tools/clang/tools/dxcreflectioncontainer/DxcReflection.cpp rename to tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index 16deb44da3..dfecc1dd03 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflection.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -7,7 +7,7 @@ // // /////////////////////////////////////////////////////////////////////////////// -#include "dxc/DxcReflection/DxcReflection.h" +#include "dxc/DxcReflection/DxcReflectionContainer.h" #include #include diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 20c0e0130d..0837dbf5da 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -7,7 +7,7 @@ // // /////////////////////////////////////////////////////////////////////////////// -#include "dxc/DxcReflection/DxcReflection.h" +#include "dxc/DxcReflection/DxcReflectionContainer.h" #include #include From 363dd6ebe3f332c9d1265b6ab83298ee42ab04ab Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 9 Nov 2025 17:20:00 +0100 Subject: [PATCH 086/126] Renamed Dxc(HLSL) prefixed types to Reflection prefix, since there is already an hlsl:: namespace and it's not necessarily DXC specific. --- .../DxcReflection/DxcReflectionContainer.h | 379 +++++++++--------- include/dxc/dxcreflect.h | 16 +- .../dxcreflection/dxcreflection_from_ast.cpp | 274 ++++++------- .../tools/dxcreflection/dxcreflector.cpp | 102 ++--- .../DxcReflectionContainer.cpp | 268 ++++++------- .../DxcReflectionJson.cpp | 110 ++--- 6 files changed, 574 insertions(+), 575 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflectionContainer.h b/include/dxc/DxcReflection/DxcReflectionContainer.h index 796debd376..396ede1b7c 100644 --- a/include/dxc/DxcReflection/DxcReflectionContainer.h +++ b/include/dxc/DxcReflection/DxcReflectionContainer.h @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // // -// DxcReflection.h // +// DxcReflectionContainer.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // @@ -22,7 +22,7 @@ namespace hlsl { -struct DxcReflectionError { +struct ReflectionError { const char *err; @@ -30,36 +30,36 @@ struct DxcReflectionError { bool hasIndex; uint8_t pad[3]; - constexpr DxcReflectionError() + constexpr ReflectionError() : err(nullptr), index(0), hasIndex(false), pad{0, 0, 0} {} - constexpr DxcReflectionError(const char *err) + constexpr ReflectionError(const char *err) : err(err), index(0), hasIndex(false), pad{0, 0, 0} {} - constexpr DxcReflectionError(const char *err, uint32_t index) + constexpr ReflectionError(const char *err, uint32_t index) : err(err), index(index), hasIndex(true), pad{0, 0, 0} {} operator const char *() const { return err; } }; -static constexpr const DxcReflectionError DxcReflectionSuccess = nullptr; +static constexpr const ReflectionError ReflectionErrorSuccess = nullptr; #ifndef NDEBUG #if defined(_MSC_VER) - #define DXC_FUNC_NAME __FUNCTION__ + #define HLSL_REFL_ERR_FUNC_NAME __FUNCTION__ #elif defined(__clang__) || defined(__GNUC__) - #define DXC_FUNC_NAME __PRETTY_FUNCTION__ + #define HLSL_REFL_ERR_FUNC_NAME __PRETTY_FUNCTION__ #else - #define DXC_FUNC_NAME __func__ + #define HLSL_REFL_ERR_FUNC_NAME __func__ #endif - #define DXC_REFLECT_STRING(x) #x - #define DXC_REFLECT_STRING2(x) DXC_REFLECT_STRING(x) - #define DXC_REFLECT_ERR(x, ...) DxcReflectionError(x " at " __FILE__ ":" DXC_REFLECT_STRING2(__LINE__) " (" DXC_FUNC_NAME ")", __VA_ARGS__) + #define HLSL_REFL_ERR_STRING(x) #x + #define HLSL_REFL_ERR_STRING2(x) HLSL_REFL_ERR_STRING(x) + #define HLSL_REFL_ERR(x, ...) ReflectionError(x " at " __FILE__ ":" HLSL_REFL_ERR_STRING2(__LINE__) " (" HLSL_REFL_ERR_FUNC_NAME ")", __VA_ARGS__) #else -#define DXC_REFLECT_ERR(x, ...) DxcReflectionError(x, __VA_ARGS__) + #define HLSL_REFL_ERR(x, ...) ReflectionError(x, __VA_ARGS__) #endif -class DxcHLSLNode { +class ReflectionNode { uint32_t LocalIdParentLo; //24 : 8 @@ -91,7 +91,7 @@ class DxcHLSLNode { ChildCountFwdBckLo |= v << 24; } - DxcHLSLNode(D3D12_HLSL_NODE_TYPE NodeType, + ReflectionNode(D3D12_HLSL_NODE_TYPE NodeType, bool IsFwdDeclare, uint32_t LocalId, uint16_t AnnotationStart, uint32_t ChildCount, uint32_t ParentId, uint8_t AnnotationCount, uint16_t SemanticId) @@ -106,39 +106,33 @@ class DxcHLSLNode { public: - DxcHLSLNode() = default; + ReflectionNode() = default; - [[nodiscard]] static DxcReflectionError - Initialize(DxcHLSLNode &OutNode, D3D12_HLSL_NODE_TYPE NodeType, + [[nodiscard]] static ReflectionError + Initialize(ReflectionNode &OutNode, D3D12_HLSL_NODE_TYPE NodeType, bool IsFwdDeclare, uint32_t LocalId, uint16_t AnnotationStart, uint32_t ChildCount, uint32_t ParentId, uint8_t AnnotationCount, uint16_t SemanticId) { if (NodeType < D3D12_HLSL_NODE_TYPE_START || NodeType > D3D12_HLSL_NODE_TYPE_END) - return DXC_REFLECT_ERR("Invalid NodeType"); + return HLSL_REFL_ERR("Invalid NodeType"); if (LocalId >= ((1u << 24) - 1)) - return DXC_REFLECT_ERR("LocalId out of bounds"); + return HLSL_REFL_ERR("LocalId out of bounds"); if (ParentId >= ((1u << 24) - 1)) - return DXC_REFLECT_ERR("ParentId out of bounds"); + return HLSL_REFL_ERR("ParentId out of bounds"); if (ChildCount >= ((1u << 24) - 1)) - return DXC_REFLECT_ERR("ChildCount out of bounds"); + return HLSL_REFL_ERR("ChildCount out of bounds"); - if (IsFwdDeclare) { + if (IsFwdDeclare && AnnotationCount) + return HLSL_REFL_ERR("Fwd declares aren't allowed to have annotations"); - if (AnnotationCount) - return DXC_REFLECT_ERR("Fwd declares aren't allowed to have annotations"); - - if (ChildCount) - return DXC_REFLECT_ERR("Fwd declares aren't allowed to have children"); - } - - OutNode = DxcHLSLNode(NodeType, IsFwdDeclare, LocalId, AnnotationStart, + OutNode = ReflectionNode(NodeType, IsFwdDeclare, LocalId, AnnotationStart, ChildCount, ParentId, AnnotationCount, SemanticId); - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } bool IsFwdDeclare() const { return Type >> 7; } @@ -168,15 +162,15 @@ class DxcHLSLNode { bool IsFwdBckDefined() const { return GetFwdBck() != ((1 << 24) - 1); } - [[nodiscard]] DxcReflectionError ResolveFwdDeclare(uint32_t SelfId, - DxcHLSLNode &Definition, + [[nodiscard]] ReflectionError ResolveFwdDeclare(uint32_t SelfId, + ReflectionNode &Definition, uint32_t DefinitionId) { if (SelfId >= ((1u << 24) - 1)) - return DXC_REFLECT_ERR("SelfId out of bounds"); + return HLSL_REFL_ERR("SelfId out of bounds"); if (DefinitionId >= ((1u << 24) - 1)) - return DXC_REFLECT_ERR("DefinitionId out of bounds"); + return HLSL_REFL_ERR("DefinitionId out of bounds"); assert(DefinitionId != SelfId && "NodeId can't be definition id!"); assert(IsFwdDeclare() && @@ -188,7 +182,7 @@ class DxcHLSLNode { SetFwdBck(DefinitionId); Definition.SetFwdBck(SelfId); - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } // For example if Enum, maps into Enums[LocalId] @@ -212,16 +206,16 @@ class DxcHLSLNode { return uint32_t(LocalIdParentLo >> 24) | (uint32_t(ParentHi) << 8); } - [[nodiscard]] DxcReflectionError IncreaseChildCount() { + [[nodiscard]] ReflectionError IncreaseChildCount() { if (GetChildCount() >= ((1u << 24) - 1)) - return DXC_REFLECT_ERR("Child count out of bounds"); + return HLSL_REFL_ERR("Child count out of bounds"); ++ChildCountFwdBckLo; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } - bool operator==(const DxcHLSLNode &other) const { + bool operator==(const ReflectionNode &other) const { return LocalIdParentLo == other.LocalIdParentLo && ParentHiAnnotationsType32 == other.ParentHiAnnotationsType32 && ChildCountFwdBckLo == other.ChildCountFwdBckLo && @@ -230,7 +224,7 @@ class DxcHLSLNode { } }; -class DxcHLSLNodeSymbol { +class ReflectionNodeSymbol { union { struct { @@ -251,7 +245,7 @@ class DxcHLSLNodeSymbol { uint64_t SourceColumnStartEndLo; }; - DxcHLSLNodeSymbol(uint32_t NameId, uint16_t FileSourceId, + ReflectionNodeSymbol(uint32_t NameId, uint16_t FileSourceId, uint16_t SourceLineCount, uint32_t SourceLineStart, uint32_t SourceColumnStart, uint32_t SourceColumnEnd) : NameId(NameId), FileSourceId(FileSourceId), @@ -264,26 +258,26 @@ class DxcHLSLNodeSymbol { public: - DxcHLSLNodeSymbol() = default; + ReflectionNodeSymbol() = default; - [[nodiscard]] static DxcReflectionError - Initialize(DxcHLSLNodeSymbol &Symbol, uint32_t NameId, uint16_t FileSourceId, + [[nodiscard]] static ReflectionError + Initialize(ReflectionNodeSymbol &Symbol, uint32_t NameId, uint16_t FileSourceId, uint16_t SourceLineCount, uint32_t SourceLineStart, uint32_t SourceColumnStart, uint32_t SourceColumnEnd) { if (SourceColumnStart >= (1u << 22)) - return DXC_REFLECT_ERR("SourceColumnStart out of bounds"); + return HLSL_REFL_ERR("SourceColumnStart out of bounds"); if (SourceColumnEnd >= (1u << 22)) - return DXC_REFLECT_ERR("SourceColumnEnd out of bounds"); + return HLSL_REFL_ERR("SourceColumnEnd out of bounds"); if (SourceLineStart >= ((1u << 20) - 1)) - return DXC_REFLECT_ERR("SourceLineStart out of bounds"); + return HLSL_REFL_ERR("SourceLineStart out of bounds"); Symbol = - DxcHLSLNodeSymbol(NameId, FileSourceId, SourceLineCount, + ReflectionNodeSymbol(NameId, FileSourceId, SourceLineCount, SourceLineStart, SourceColumnStart, SourceColumnEnd); - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } @@ -305,37 +299,36 @@ class DxcHLSLNodeSymbol { return SourceColumnEndLo | ((ColumnHiSourceLinePad & (0x3F << 6)) << 10); } - bool operator==(const DxcHLSLNodeSymbol &other) const { + bool operator==(const ReflectionNodeSymbol &other) const { return NameIdFileNameIdSourceLineCount == other.NameIdFileNameIdSourceLineCount && SourceColumnStartEndLo == other.SourceColumnStartEndLo; } }; -struct DxcHLSLEnumDesc { +struct ReflectionEnumeration { uint32_t NodeId; D3D12_HLSL_ENUM_TYPE Type; - bool operator==(const DxcHLSLEnumDesc &other) const { + bool operator==(const ReflectionEnumeration &other) const { return NodeId == other.NodeId && Type == other.Type; } }; -struct DxcHLSLEnumValue { +struct ReflectionEnumValue { int64_t Value; uint32_t NodeId; - bool operator==(const DxcHLSLEnumValue &other) const { + bool operator==(const ReflectionEnumValue &other) const { return Value == other.Value && NodeId == other.NodeId; } }; - -struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC without duplicating - // data (typeId holds some) +struct ReflectionFunctionParameter { // Mirrors D3D12_PARAMETER_DESC without + // duplicating data (typeId holds some) uint32_t TypeId; uint32_t NodeId; @@ -344,7 +337,7 @@ struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC without duplicating uint8_t Flags; // D3D_PARAMETER_FLAGS uint16_t Padding; - bool operator==(const DxcHLSLParameter &other) const { + bool operator==(const ReflectionFunctionParameter &other) const { return TypeId == other.TypeId && NodeId == other.NodeId && InterpolationMode == other.InterpolationMode && Flags == other.Flags; } @@ -355,32 +348,31 @@ struct DxcHLSLParameter { // Mirrors D3D12_PARAMETER_DESC without duplicating // - if HasConditionVar(): a variable in the condition // - NodeCount children (If: children ex. else body, For: init children) // - Rest of the body (If: else body, otherwise: normal body) -class DxcHLSLStatement { +class ReflectionScopeStmt { uint32_t NodeId; uint32_t NodeCount_HasConditionVar_HasElse; - DxcHLSLStatement(uint32_t NodeId, uint32_t NodeCount, bool HasConditionVar, - bool IfAndHasElse) + ReflectionScopeStmt(uint32_t NodeId, uint32_t NodeCount, bool HasConditionVar, + bool IfAndHasElse) : NodeId(NodeId), NodeCount_HasConditionVar_HasElse(NodeCount | (HasConditionVar ? (1u << 30) : 0) | (IfAndHasElse ? (1u << 31) : 0)) {} public: + ReflectionScopeStmt() = default; - DxcHLSLStatement() = default; - - [[nodiscard]] static DxcReflectionError - Initialize(DxcHLSLStatement &Statement, uint32_t NodeId, uint32_t NodeCount, - bool HasConditionVar, bool IfAndHasElse) { + [[nodiscard]] static ReflectionError + Initialize(ReflectionScopeStmt &Statement, uint32_t NodeId, + uint32_t NodeCount, bool HasConditionVar, bool IfAndHasElse) { if (NodeCount >= (1u << 30)) - return DXC_REFLECT_ERR("NodeCount out of bounds"); + return HLSL_REFL_ERR("NodeCount out of bounds"); Statement = - DxcHLSLStatement(NodeId, NodeCount, HasConditionVar, IfAndHasElse); - return DxcReflectionSuccess; + ReflectionScopeStmt(NodeId, NodeCount, HasConditionVar, IfAndHasElse); + return ReflectionErrorSuccess; } uint32_t GetNodeId() const { return NodeId; } @@ -398,38 +390,38 @@ class DxcHLSLStatement { } bool HasElse() const { return (NodeCount_HasConditionVar_HasElse >> 31) & 1; } - bool operator==(const DxcHLSLStatement &Other) const { + bool operator==(const ReflectionScopeStmt &Other) const { return NodeId == Other.NodeId && NodeCount_HasConditionVar_HasElse == Other.NodeCount_HasConditionVar_HasElse; } }; -class DxcHLSLFunction { +class ReflectionFunction { uint32_t NodeId; uint32_t NumParametersHasReturnAndDefinition; - DxcHLSLFunction(uint32_t NodeId, uint32_t NumParameters, bool HasReturn, - bool HasDefinition) + ReflectionFunction(uint32_t NodeId, uint32_t NumParameters, bool HasReturn, + bool HasDefinition) : NodeId(NodeId), NumParametersHasReturnAndDefinition(NumParameters | (HasReturn ? (1u << 30) : 0) | - (HasDefinition ? (1u << 31) : 0)) { } + (HasDefinition ? (1u << 31) : 0)) {} public: + ReflectionFunction() = default; - DxcHLSLFunction() = default; - - [[nodiscard]] static DxcReflectionError Initialize(DxcHLSLFunction &Function, uint32_t NodeId, - uint32_t NumParameters, bool HasReturn, - bool HasDefinition) { + [[nodiscard]] static ReflectionError + Initialize(ReflectionFunction &Function, uint32_t NodeId, + uint32_t NumParameters, bool HasReturn, bool HasDefinition) { if (NumParameters >= (1u << 30)) - return DXC_REFLECT_ERR("NumParameters out of bounds"); + return HLSL_REFL_ERR("NumParameters out of bounds"); - Function = DxcHLSLFunction(NodeId, NumParameters, HasReturn, HasDefinition); - return DxcReflectionSuccess; + Function = + ReflectionFunction(NodeId, NumParameters, HasReturn, HasDefinition); + return ReflectionErrorSuccess; } uint32_t GetNodeId() const { return NodeId; } @@ -446,16 +438,17 @@ class DxcHLSLFunction { return (NumParametersHasReturnAndDefinition >> 31) & 1; } - bool operator==(const DxcHLSLFunction &other) const { + bool operator==(const ReflectionFunction &other) const { return NodeId == other.NodeId && NumParametersHasReturnAndDefinition == other.NumParametersHasReturnAndDefinition; } }; -class DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus - // the Name (and uID replaced with NodeID) and added - // arrayIndex and better packing +class ReflectionShaderResource { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, + // minus + // the Name (and uID replaced with NodeID) and added + // arrayIndex and better packing union { struct { @@ -480,39 +473,39 @@ class DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus uint64_t ArrayIdBufferId; }; - DxcHLSLRegister(D3D_SHADER_INPUT_TYPE Type, uint32_t BindCount, - uint32_t uFlags, D3D_RESOURCE_RETURN_TYPE ReturnType, - D3D_SRV_DIMENSION Dimension, uint32_t NodeId, - uint32_t ArrayId, uint32_t BufferId) + ReflectionShaderResource(D3D_SHADER_INPUT_TYPE Type, uint32_t BindCount, + uint32_t uFlags, D3D_RESOURCE_RETURN_TYPE ReturnType, + D3D_SRV_DIMENSION Dimension, uint32_t NodeId, + uint32_t ArrayId, uint32_t BufferId) : Type(Type), BindCount(BindCount), uFlags(uFlags), ReturnType(ReturnType), Dimension(Dimension), NodeId(NodeId), ArrayId(ArrayId), BufferId(BufferId) {} public: - DxcHLSLRegister() = default; + ReflectionShaderResource() = default; - [[nodiscard]] static DxcReflectionError - Initialize(DxcHLSLRegister &Register, D3D_SHADER_INPUT_TYPE Type, + [[nodiscard]] static ReflectionError + Initialize(ReflectionShaderResource &Register, D3D_SHADER_INPUT_TYPE Type, uint32_t BindCount, uint32_t uFlags, D3D_RESOURCE_RETURN_TYPE ReturnType, D3D_SRV_DIMENSION Dimension, uint32_t NodeId, uint32_t ArrayId, uint32_t BufferId) { if (Type < D3D_SIT_CBUFFER || Type > D3D_SIT_UAV_FEEDBACKTEXTURE) - return DXC_REFLECT_ERR("Invalid type"); + return HLSL_REFL_ERR("Invalid type"); if (ReturnType < 0 || ReturnType > D3D_RETURN_TYPE_CONTINUED) - return DXC_REFLECT_ERR("Invalid return type"); + return HLSL_REFL_ERR("Invalid return type"); if (Dimension < D3D_SRV_DIMENSION_UNKNOWN || Dimension > D3D_SRV_DIMENSION_BUFFEREX) - return DXC_REFLECT_ERR("Invalid srv dimension"); + return HLSL_REFL_ERR("Invalid srv dimension"); if (uFlags >> 8) - return DXC_REFLECT_ERR("Invalid user flags"); + return HLSL_REFL_ERR("Invalid user flags"); - Register = DxcHLSLRegister(Type, BindCount, uFlags, ReturnType, Dimension, - NodeId, ArrayId, BufferId); - return DxcReflectionSuccess; + Register = ReflectionShaderResource(Type, BindCount, uFlags, ReturnType, + Dimension, NodeId, ArrayId, BufferId); + return ReflectionErrorSuccess; } D3D_RESOURCE_RETURN_TYPE GetReturnType() const { @@ -530,37 +523,37 @@ class DxcHLSLRegister { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, minus uint32_t GetArrayId() const { return ArrayId; } uint32_t GetBufferId() const { return BufferId; } - bool operator==(const DxcHLSLRegister &other) const { + bool operator==(const ReflectionShaderResource &other) const { return TypeDimensionReturnTypeFlagsBindCount == other.TypeDimensionReturnTypeFlagsBindCount && NodeId == other.NodeId && ArrayIdBufferId == other.ArrayIdBufferId; } }; -class DxcHLSLArray { +class ReflectionArray { uint32_t ArrayElemStart; - DxcHLSLArray(uint32_t ArrayElem, uint32_t ArrayStart) + ReflectionArray(uint32_t ArrayElem, uint32_t ArrayStart) : ArrayElemStart((ArrayElem << 26) | ArrayStart) {} public: - DxcHLSLArray() = default; + ReflectionArray() = default; - [[nodiscard]] static DxcReflectionError Initialize(DxcHLSLArray &Arr, uint32_t ArrayElem, uint32_t ArrayStart) { + [[nodiscard]] static ReflectionError Initialize(ReflectionArray &Arr, uint32_t ArrayElem, uint32_t ArrayStart) { if (ArrayElem <= 1 || ArrayElem > 32) - return DXC_REFLECT_ERR("ArrayElem out of bounds"); + return HLSL_REFL_ERR("ArrayElem out of bounds"); if (ArrayStart >= (1u << 26)) - return DXC_REFLECT_ERR("ArrayStart out of bounds"); + return HLSL_REFL_ERR("ArrayStart out of bounds"); - Arr = DxcHLSLArray(ArrayElem, ArrayStart); - return DxcReflectionSuccess; + Arr = ReflectionArray(ArrayElem, ArrayStart); + return ReflectionErrorSuccess; } - bool operator==(const DxcHLSLArray &Other) const { + bool operator==(const ReflectionArray &Other) const { return Other.ArrayElemStart == ArrayElemStart; } @@ -568,12 +561,12 @@ class DxcHLSLArray { uint32_t ArrayStart() const { return ArrayElemStart << 6 >> 6; } }; -struct DxcHLSLArrayOrElements { +struct ReflectionArrayOrElements { uint32_t ElementsOrArrayId; - DxcHLSLArrayOrElements() = default; - DxcHLSLArrayOrElements(uint32_t arrayId, uint32_t arraySize) + ReflectionArrayOrElements() = default; + ReflectionArrayOrElements(uint32_t arrayId, uint32_t arraySize) : ElementsOrArrayId(arrayId != (uint32_t)-1 ? ((1u << 31) | arrayId) : (arraySize > 1 ? arraySize : 0)) {} @@ -591,14 +584,14 @@ struct DxcHLSLArrayOrElements { : (uint32_t)-1; } - bool operator==(const DxcHLSLArrayOrElements &Other) const { + bool operator==(const ReflectionArrayOrElements &Other) const { return Other.ElementsOrArrayId == ElementsOrArrayId; } }; -class DxcHLSLType { // Almost maps to CShaderReflectionType and - // D3D12_SHADER_TYPE_DESC, but tightly packed and - // easily serializable +class ReflectionVariableType { // Almost maps to CShaderReflectionType and + // D3D12_SHADER_TYPE_DESC, but tightly packed and + // easily serializable uint32_t MemberData; // 24 : 8 (start, count) @@ -615,22 +608,24 @@ class DxcHLSLType { // Almost maps to CShaderReflectionType and uint32_t BaseClass; // -1 if none, otherwise a type index uint32_t InterfaceOffsetAndCount; // 24 : 8 (start, count) - DxcHLSLArrayOrElements UnderlyingArray; //No sugar (e.g. F32x4a4 in using F32x4a4 = F32x4[4] becomes float4[4]) - - DxcHLSLType(uint32_t BaseClass, - DxcHLSLArrayOrElements ElementsOrArrayIdUnderlying, - D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE Type, - uint8_t Rows, uint8_t Columns, uint32_t MembersCount, - uint32_t MembersStart, uint32_t InterfaceOffset, - uint32_t InterfaceCount) + ReflectionArrayOrElements + UnderlyingArray; // No sugar (e.g. F32x4a4 in using F32x4a4 = F32x4[4] + // becomes float4[4]) + + ReflectionVariableType(uint32_t BaseClass, + ReflectionArrayOrElements ElementsOrArrayIdUnderlying, + D3D_SHADER_VARIABLE_CLASS Class, + D3D_SHADER_VARIABLE_TYPE Type, uint8_t Rows, + uint8_t Columns, uint32_t MembersCount, + uint32_t MembersStart, uint32_t InterfaceOffset, + uint32_t InterfaceCount) : MemberData(MembersStart | (MembersCount << 24)), Class(Class), Type(Type), Rows(Rows), Columns(Columns), UnderlyingArray(ElementsOrArrayIdUnderlying), BaseClass(BaseClass), InterfaceOffsetAndCount(InterfaceOffset | (InterfaceCount << 24)) {} public: - - bool operator==(const DxcHLSLType &Other) const { + bool operator==(const ReflectionVariableType &Other) const { return Other.MemberData == MemberData && Other.UnderlyingArray == UnderlyingArray && ClassTypeRowsColums == Other.ClassTypeRowsColums && @@ -653,54 +648,56 @@ class DxcHLSLType { // Almost maps to CShaderReflectionType and uint32_t GetMemberCount() const { return MemberData >> 24; } uint32_t GetMemberStart() const { return MemberData << 8 >> 8; } - - DxcHLSLArrayOrElements GetUnderlyingArray() const { return UnderlyingArray; } + + ReflectionArrayOrElements GetUnderlyingArray() const { + return UnderlyingArray; + } uint32_t GetInterfaceCount() const { return InterfaceOffsetAndCount >> 24; } uint32_t GetInterfaceStart() const { return InterfaceOffsetAndCount << 8 >> 8; } - DxcHLSLType() = default; + ReflectionVariableType() = default; - [[nodiscard]] static DxcReflectionError - Initialize(DxcHLSLType &Type, uint32_t BaseClass, - DxcHLSLArrayOrElements ElementsOrArrayIdUnderlying, - D3D_SHADER_VARIABLE_CLASS Class, D3D_SHADER_VARIABLE_TYPE VariableType, - uint8_t Rows, uint8_t Columns, uint32_t MembersCount, - uint32_t MembersStart, uint32_t InterfaceOffset, - uint32_t InterfaceCount) { + [[nodiscard]] static ReflectionError + Initialize(ReflectionVariableType &Type, uint32_t BaseClass, + ReflectionArrayOrElements ElementsOrArrayIdUnderlying, + D3D_SHADER_VARIABLE_CLASS Class, + D3D_SHADER_VARIABLE_TYPE VariableType, uint8_t Rows, + uint8_t Columns, uint32_t MembersCount, uint32_t MembersStart, + uint32_t InterfaceOffset, uint32_t InterfaceCount) { if (Class < D3D_SVC_SCALAR || Class > D3D_SVC_INTERFACE_POINTER) - return DXC_REFLECT_ERR("Invalid class"); + return HLSL_REFL_ERR("Invalid class"); if (VariableType < D3D_SVT_VOID || VariableType > D3D_SVT_UINT64) - return DXC_REFLECT_ERR("Invalid type"); + return HLSL_REFL_ERR("Invalid type"); if (MembersStart >= (1u << 24)) - return DXC_REFLECT_ERR("Member start out of bounds"); + return HLSL_REFL_ERR("Member start out of bounds"); if (InterfaceOffset >= (1u << 24)) - return DXC_REFLECT_ERR("Interface start out of bounds"); + return HLSL_REFL_ERR("Interface start out of bounds"); if (MembersCount >= (1u << 8)) - return DXC_REFLECT_ERR("Member count out of bounds"); + return HLSL_REFL_ERR("Member count out of bounds"); if (InterfaceCount >= (1u << 8)) - return DXC_REFLECT_ERR("Interface count out of bounds"); + return HLSL_REFL_ERR("Interface count out of bounds"); - Type = DxcHLSLType(BaseClass, ElementsOrArrayIdUnderlying, Class, - VariableType, Rows, Columns, MembersCount, MembersStart, - InterfaceOffset, InterfaceCount); - return DxcReflectionSuccess; + Type = ReflectionVariableType( + BaseClass, ElementsOrArrayIdUnderlying, Class, VariableType, Rows, + Columns, MembersCount, MembersStart, InterfaceOffset, InterfaceCount); + return ReflectionErrorSuccess; } }; -struct DxcHLSLTypeSymbol { +struct ReflectionVariableTypeSymbol { // Keep sugar (F32x4a4 = F32x4[4] stays F32x4a4, doesn't become float4[4] like // in underlying name + array) - DxcHLSLArrayOrElements DisplayArray; + ReflectionArrayOrElements DisplayArray; // For example F32x4[4] stays F32x4 (array in DisplayArray) uint32_t DisplayNameId; @@ -708,52 +705,54 @@ struct DxcHLSLTypeSymbol { // F32x4[4] would turn into float4 (array in UnderlyingArray) uint32_t UnderlyingNameId; - bool operator==(const DxcHLSLTypeSymbol &Other) const { + bool operator==(const ReflectionVariableTypeSymbol &Other) const { return Other.DisplayArray == DisplayArray && DisplayNameId == Other.DisplayNameId && UnderlyingNameId == Other.UnderlyingNameId; } - DxcHLSLTypeSymbol() = default; - DxcHLSLTypeSymbol(DxcHLSLArrayOrElements ElementsOrArrayIdDisplay, + ReflectionVariableTypeSymbol() = default; + ReflectionVariableTypeSymbol(ReflectionArrayOrElements ElementsOrArrayIdDisplay, uint32_t DisplayNameId, uint32_t UnderlyingNameId) : DisplayArray(ElementsOrArrayIdDisplay), DisplayNameId(DisplayNameId), UnderlyingNameId(UnderlyingNameId) {} }; -struct DxcHLSLBuffer { // Almost maps to CShaderReflectionConstantBuffer and - // D3D12_SHADER_BUFFER_DESC +struct ReflectionShaderBuffer { // Almost maps to + // CShaderReflectionConstantBuffer and + // D3D12_SHADER_BUFFER_DESC D3D_CBUFFER_TYPE Type; uint32_t NodeId; - bool operator==(const DxcHLSLBuffer &other) const { + bool operator==(const ReflectionShaderBuffer &other) const { return Type == other.Type && NodeId == other.NodeId; } }; -class DxcHLSLAnnotation { +class ReflectionAnnotation { uint32_t StringNonDebugAndIsBuiltin; - DxcHLSLAnnotation(uint32_t StringNonDebug, bool IsBuiltin) + ReflectionAnnotation(uint32_t StringNonDebug, bool IsBuiltin) : StringNonDebugAndIsBuiltin(StringNonDebug | (IsBuiltin ? (1u << 31) : 0)) {} -public: - DxcHLSLAnnotation() = default; +public: + ReflectionAnnotation() = default; - [[nodiscard]] static DxcReflectionError - Initialize(DxcHLSLAnnotation &Annotation, uint32_t StringNonDebug, bool IsBuiltin) { + [[nodiscard]] static ReflectionError + Initialize(ReflectionAnnotation &Annotation, uint32_t StringNonDebug, + bool IsBuiltin) { if (StringNonDebug >= (1u << 31)) - return DXC_REFLECT_ERR("String non debug out of bounds"); + return HLSL_REFL_ERR("String non debug out of bounds"); - Annotation = DxcHLSLAnnotation(StringNonDebug, IsBuiltin); - return DxcReflectionSuccess; + Annotation = ReflectionAnnotation(StringNonDebug, IsBuiltin); + return ReflectionErrorSuccess; } - bool operator==(const DxcHLSLAnnotation &other) const { + bool operator==(const ReflectionAnnotation &other) const { return StringNonDebugAndIsBuiltin == other.StringNonDebugAndIsBuiltin; } @@ -766,9 +765,9 @@ class DxcHLSLAnnotation { //Note: Regarding nodes, node 0 is the root node (global scope) // If a node is a fwd declare you should inspect the fwd node id. -// If a node isn't a fwd declare but has a backward id, it should be ignored during traversal. -// This node can be defined in a different namespace or type while it's declared elsewhere. -struct DxcHLSLReflectionData { +// If a node isn't a fwd declare but has a backward id, the node should be ignored during traversal. +// (That node can be defined in a different namespace or type while it's declared elsewhere). +struct ReflectionData { D3D12_HLSL_REFLECTION_FEATURE Features{}; @@ -781,32 +780,32 @@ struct DxcHLSLReflectionData { std::vector Sources; std::unordered_map StringToSourceId; - std::vector Nodes; // 0 = Root node (global scope) + std::vector Nodes; // 0 = Root node (global scope) - std::vector Registers; - std::vector Functions; + std::vector Registers; + std::vector Functions; - std::vector Enums; - std::vector EnumValues; + std::vector Enums; + std::vector EnumValues; - std::vector Parameters; - std::vector Annotations; + std::vector Parameters; + std::vector Annotations; - std::vector Arrays; + std::vector Arrays; std::vector ArraySizes; std::vector MemberTypeIds; std::vector TypeList; - std::vector Types; - std::vector Buffers; + std::vector Types; + std::vector Buffers; - std::vector Statements; + std::vector Statements; // Can be stripped if !(D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) - std::vector NodeSymbols; + std::vector NodeSymbols; std::vector MemberNameIds; - std::vector TypeSymbols; + std::vector TypeSymbols; // Only generated if deserialized with MakeNameLookupTable or // GenerateNameLookupTable is called (and if symbols aren't stripped) @@ -815,13 +814,13 @@ struct DxcHLSLReflectionData { std::vector NodeIdToFullyResolved; std::unordered_map FullyResolvedToMemberId; - [[nodiscard]] DxcReflectionError + [[nodiscard]] ReflectionError RegisterString(uint32_t &StringId, const std::string &Name, bool IsNonDebug); - [[nodiscard]] DxcReflectionError PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, + [[nodiscard]] ReflectionError PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, const std::vector &ArraySize); - [[nodiscard]] DxcReflectionError + [[nodiscard]] ReflectionError RegisterTypeList(const std::vector &TypeIds, uint32_t &Offset, uint8_t &Len); @@ -832,11 +831,11 @@ struct DxcHLSLReflectionData { void StripSymbols(); bool GenerateNameLookupTable(); - DxcHLSLReflectionData() = default; - [[nodiscard]] DxcReflectionError Deserialize(const std::vector &Bytes, + ReflectionData() = default; + [[nodiscard]] ReflectionError Deserialize(const std::vector &Bytes, bool MakeNameLookupTable); - bool IsSameNonDebug(const DxcHLSLReflectionData &Other) const { + bool IsSameNonDebug(const ReflectionData &Other) const { return StringsNonDebug == Other.StringsNonDebug && Nodes == Other.Nodes && Registers == Other.Registers && Functions == Other.Functions && Enums == Other.Enums && EnumValues == Other.EnumValues && @@ -847,7 +846,7 @@ struct DxcHLSLReflectionData { Parameters == Other.Parameters && Statements == Other.Statements; } - bool operator==(const DxcHLSLReflectionData &Other) const { + bool operator==(const ReflectionData &Other) const { return IsSameNonDebug(Other) && Strings == Other.Strings && Sources == Other.Sources && NodeSymbols == Other.NodeSymbols && MemberNameIds == Other.MemberNameIds && diff --git a/include/dxc/dxcreflect.h b/include/dxc/dxcreflect.h index 43e20ea1e2..6015853f0e 100644 --- a/include/dxc/dxcreflect.h +++ b/include/dxc/dxcreflect.h @@ -21,11 +21,13 @@ #define CLSID_SCOPE #endif -//Expose HLSL reflection before DXIL/SPIRV generation. -//(Ran after the preprocessed HLSL is obtained). -//This is useful to avoid custom parsers from reinventing the wheel. -//You could use it to find all entrypoints even if [shader("")] isn't used, -//Find struct/enum information, find out about optimized out registers, etc. +// Expose HLSL reflection before DXIL/SPIRV generation. +// (Ran after the preprocessed HLSL is obtained). +// This is useful to avoid custom parsers from reinventing the wheel. +// You could use it to find all entrypoints even if [shader("")] isn't used, +// Find struct/enum information, find out about optimized out registers, etc. +// This is a limited AST that doesn't include anything beyond symbols +// (so no details about instructions). enum D3D12_HLSL_REFLECTION_FEATURE { @@ -67,7 +69,7 @@ operator~(D3D12_HLSL_REFLECTION_FEATURE a) { struct D3D12_HLSL_REFLECTION_DESC { D3D12_HLSL_REFLECTION_FEATURE Features; - UINT ConstantBufferCount; + UINT BufferCount; UINT ResourceCount; UINT FunctionCount; UINT EnumCount; @@ -178,8 +180,6 @@ struct D3D12_HLSL_NODE_SYMBOL { UINT ColumnEnd; }; -// TODO: Move to d3d12shader.h - struct D3D12_ARRAY_DESC { UINT ArrayDims; UINT ArrayLengths[32]; // SPV_REFLECT_MAX_ARRAY_DIMS diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 095658a961..e0c8fed929 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -24,8 +24,8 @@ using namespace clang; namespace hlsl { -static [[nodiscard]] DxcReflectionError -PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManager &SM, +static [[nodiscard]] ReflectionError +PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, const LangOptions &LangOpts, const std::string &UnqualifiedName, const Decl *DeclSelf, D3D12_HLSL_NODE_TYPE Type, uint32_t ParentNodeId, uint32_t LocalId, @@ -34,10 +34,10 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage { if (Refl.Nodes.size() >= (1u << 24)) - return DXC_REFLECT_ERR("Nodes overflow"); + return HLSL_REFL_ERR("Nodes overflow"); if (LocalId >= (1u << 24)) - return DXC_REFLECT_ERR("LocalId overflow"); + return HLSL_REFL_ERR("LocalId overflow"); uint32_t nodeId = Refl.Nodes.size(); @@ -51,24 +51,24 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage if (const AnnotateAttr *annotate = dyn_cast(attr)) { if (Refl.Annotations.size() >= (1u << 16)) - return DXC_REFLECT_ERR("Out of annotations"); + return HLSL_REFL_ERR("Out of annotations"); Refl.Annotations.push_back({}); uint32_t stringId; - if (DxcReflectionError err = + if (ReflectionError err = Refl.RegisterString(stringId, annotate->getAnnotation().str(), true)) return err; - if (DxcReflectionError err = DxcHLSLAnnotation::Initialize( + if (ReflectionError err = ReflectionAnnotation::Initialize( Refl.Annotations.back(), stringId, false)) return err; if (annotationCount >= uint8_t(-1)) - return DXC_REFLECT_ERR("Annotation count out of bounds"); + return HLSL_REFL_ERR("Annotation count out of bounds"); ++annotationCount; @@ -76,24 +76,24 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage dyn_cast(attr)) { if (Refl.Annotations.size() >= (1u << 16)) - return DXC_REFLECT_ERR("Out of annotations"); + return HLSL_REFL_ERR("Out of annotations"); Refl.Annotations.push_back({}); uint32_t stringId; - if (DxcReflectionError err = Refl.RegisterString( + if (ReflectionError err = Refl.RegisterString( stringId, "shader(\"" + shaderAttr->getStage().str() + "\")", true)) return err; - if (DxcReflectionError err = DxcHLSLAnnotation::Initialize( + if (ReflectionError err = ReflectionAnnotation::Initialize( Refl.Annotations.back(), stringId, true)) return err; if (annotationCount >= uint8_t(-1)) - return DXC_REFLECT_ERR("Annotation count out of bounds"); + return HLSL_REFL_ERR("Annotation count out of bounds"); ++annotationCount; } @@ -109,7 +109,7 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage uint32_t semanticId32; - if (DxcReflectionError err = Refl.RegisterString( + if (ReflectionError err = Refl.RegisterString( semanticId32, cast(*It)->SemanticName.str(), true)) @@ -146,7 +146,7 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage if (isFwdDeclare && rec->isImplicit()) { // Inner ghost node NodeId = uint32_t(-1); - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } } } @@ -160,7 +160,7 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage // Multiple fwd declare, ignore if (isFwdDeclare && FwdDecls->find(fwdDeclare) != FwdDecls->end()) { NodeId = uint32_t(-1); - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } if (isFwdDeclare) @@ -168,7 +168,7 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage } Refl.Nodes.push_back({}); - if (DxcReflectionError err = DxcHLSLNode::Initialize( + if (ReflectionError err = ReflectionNode::Initialize( Refl.Nodes.back(), Type, isFwdDeclare, LocalId, annotationStart, 0, ParentNodeId, annotationCount, semanticId)) return err; @@ -207,7 +207,7 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage std::string fileName = presumed.getFilename(); if (fileName != presumedEnd.getFilename()) - return DXC_REFLECT_ERR("End and start are not in the same file"); + return HLSL_REFL_ERR("End and start are not in the same file"); auto it = Refl.StringToSourceId.find(fileName); uint32_t i; @@ -217,7 +217,7 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage i = uint32_t(Refl.Sources.size()); uint32_t stringId; - if (DxcReflectionError err = + if (ReflectionError err = Refl.RegisterString(stringId, fileName, false)) return err; @@ -230,19 +230,19 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage } if (i >= 65535) - return DXC_REFLECT_ERR("Source file count is limited to 16-bit"); + return HLSL_REFL_ERR("Source file count is limited to 16-bit"); if ((endLine - startLine) >= 65535) - return DXC_REFLECT_ERR("Source line count is limited to 16-bit"); + return HLSL_REFL_ERR("Source line count is limited to 16-bit"); if (startLine >= 1048576) - return DXC_REFLECT_ERR("Source line start is limited to 20-bit"); + return HLSL_REFL_ERR("Source line start is limited to 20-bit"); if (startCol >= (1u << 22)) - return DXC_REFLECT_ERR("Column start is limited to 22-bit"); + return HLSL_REFL_ERR("Column start is limited to 22-bit"); if (endCol >= (1u << 22)) - return DXC_REFLECT_ERR("Column end is limited to 22-bit"); + return HLSL_REFL_ERR("Column end is limited to 22-bit"); sourceLineCount = uint16_t(endLine - startLine + 1); sourceLineStart = startLine; @@ -254,13 +254,13 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage uint32_t nameId; - if (DxcReflectionError err = + if (ReflectionError err = Refl.RegisterString(nameId, UnqualifiedName, false)) return err; Refl.NodeSymbols.push_back({}); - if(DxcReflectionError err = DxcHLSLNodeSymbol::Initialize(Refl.NodeSymbols.back(), nameId, sourceId, sourceLineCount, sourceLineStart, + if(ReflectionError err = ReflectionNodeSymbol::Initialize(Refl.NodeSymbols.back(), nameId, sourceId, sourceLineCount, sourceLineStart, sourceColumnStart, sourceColumnEnd)) return err; } @@ -271,7 +271,7 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage assert(FwdDecls && "Referencing fwd decl requires FwdDecls map to be present"); uint32_t fwd = (*FwdDecls)[fwdDeclare]; - if (DxcReflectionError err = + if (ReflectionError err = Refl.Nodes[fwd].ResolveFwdDeclare(fwd, Refl.Nodes[currId], currId)) return err; } @@ -280,19 +280,19 @@ PushNextNodeId(uint32_t &NodeId, DxcHLSLReflectionData &Refl, const SourceManage while (parentParent != 0) { - DxcHLSLNode &parent = Refl.Nodes[parentParent]; + ReflectionNode &parent = Refl.Nodes[parentParent]; - if (DxcReflectionError err = parent.IncreaseChildCount()) + if (ReflectionError err = parent.IncreaseChildCount()) return err; parentParent = parent.GetParentId(); } - if (DxcReflectionError err = Refl.Nodes[0].IncreaseChildCount()) + if (ReflectionError err = Refl.Nodes[0].IncreaseChildCount()) return err; NodeId = nodeId; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } struct DxcRegisterTypeInfo { @@ -514,7 +514,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); } -[[nodiscard]] DxcReflectionError GenerateTypeInfo(uint32_t &TypeId, ASTContext &ASTCtx, DxcHLSLReflectionData &Refl, +[[nodiscard]] ReflectionError GenerateTypeInfo(uint32_t &TypeId, ASTContext &ASTCtx, ReflectionData &Refl, QualType Original, bool DefaultRowMaj) { // Unwrap array @@ -616,18 +616,18 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, uint32_t arrayIdUnderlying; - if (DxcReflectionError err = Refl.PushArray( + if (ReflectionError err = Refl.PushArray( arrayIdUnderlying, arraySizeUnderlying, arrayElemUnderlying)) return err; - DxcHLSLArrayOrElements elementsOrArrayIdUnderlying(arrayIdUnderlying, arraySizeUnderlying); + ReflectionArrayOrElements elementsOrArrayIdUnderlying(arrayIdUnderlying, arraySizeUnderlying); uint32_t arrayIdDisplay; - if (DxcReflectionError err = + if (ReflectionError err = Refl.PushArray(arrayIdDisplay, arraySizeDisplay, arrayElemDisplay)) return err; - DxcHLSLArrayOrElements elementsOrArrayIdDisplay(arrayIdDisplay, arraySizeDisplay); + ReflectionArrayOrElements elementsOrArrayIdDisplay(arrayIdDisplay, arraySizeDisplay); //Unwrap vector and matrix //And base type @@ -751,13 +751,13 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, uint32_t nameId = uint32_t(-1); if (hasSymbols) - if (DxcReflectionError err = + if (ReflectionError err = Refl.RegisterString(nameId, innerTypeName, false)) return err; uint32_t typeId; - if (DxcReflectionError err = + if (ReflectionError err = GenerateTypeInfo(typeId, ASTCtx, Refl, innerType, DefaultRowMaj)) return err; @@ -788,7 +788,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, uint32_t interfaceId; - if (DxcReflectionError err = GenerateTypeInfo( + if (ReflectionError err = GenerateTypeInfo( interfaceId, ASTCtx, Refl, qualType, DefaultRowMaj)) return err; @@ -799,7 +799,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, assert(baseType == uint32_t(-1) && "Multiple base types isn't supported in HLSL"); - if (DxcReflectionError err = GenerateTypeInfo( + if (ReflectionError err = GenerateTypeInfo( baseType, ASTCtx, Refl, qualType, DefaultRowMaj)) return err; } @@ -825,7 +825,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, if (hasSymbols) { - if (DxcReflectionError err = Refl.RegisterString(nameId, name, false)) + if (ReflectionError err = Refl.RegisterString(nameId, name, false)) return err; Refl.MemberNameIds.push_back(nameId); @@ -839,7 +839,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, Refl.MemberTypeIds.resize(Refl.MemberTypeIds.size() + membersCount); if (Refl.MemberTypeIds.size() >= uint32_t(1u << 24)) - return DXC_REFLECT_ERR("Members out of bounds"); + return HLSL_REFL_ERR("Members out of bounds"); } // Initialize member types (because it causes recursion) @@ -854,7 +854,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, continue; uint32_t memberTypeId; - if (DxcReflectionError err = + if (ReflectionError err = GenerateTypeInfo(memberTypeId, ASTCtx, Refl, fieldDecl->getType(), DefaultRowMaj)) return err; @@ -959,7 +959,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, break; default: - return DXC_REFLECT_ERR("Invalid builtin type"); + return HLSL_REFL_ERR("Invalid builtin type"); } } @@ -985,19 +985,19 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, //Insert if (Refl.Types.size() >= uint32_t(-1)) - return DXC_REFLECT_ERR("Type id out of bounds"); + return HLSL_REFL_ERR("Type id out of bounds"); if (interfaces.size() >= uint8_t(-1)) - return DXC_REFLECT_ERR("Only allowing 256 interfaces"); + return HLSL_REFL_ERR("Only allowing 256 interfaces"); uint32_t interfaceOffset = 0; uint8_t interfaceCount = 0; - if (DxcReflectionError err = + if (ReflectionError err = Refl.RegisterTypeList(interfaces, interfaceOffset, interfaceCount)) return err; - DxcHLSLType hlslType; - if (DxcReflectionError err = DxcHLSLType::Initialize( + ReflectionVariableType hlslType; + if (ReflectionError err = ReflectionVariableType::Initialize( hlslType, baseType, elementsOrArrayIdUnderlying, cls, type, rows, columns, membersCount, membersOffset, interfaceOffset, interfaceCount)) @@ -1008,16 +1008,16 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, if (hasSymbols) { - if (DxcReflectionError err = + if (ReflectionError err = Refl.RegisterString(displayNameId, displayName, false)) return err; - if (DxcReflectionError err = + if (ReflectionError err = Refl.RegisterString(underlyingNameId, underlyingName, false)) return err; } - DxcHLSLTypeSymbol typeSymbol(elementsOrArrayIdDisplay, displayNameId, + ReflectionVariableTypeSymbol typeSymbol(elementsOrArrayIdDisplay, displayNameId, underlyingNameId); uint32_t i = 0; @@ -1037,14 +1037,14 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, } TypeId = i; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } -[[nodiscard]] static DxcReflectionError FillReflectionRegisterAt( +[[nodiscard]] static ReflectionError FillReflectionRegisterAt( const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, ValueDecl *ValDesc, const std::vector &ArraySize, - DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, + ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId, bool DefaultRowMaj) { ArrayRef UA = ValDesc->getUnusualAnnotations(); @@ -1052,7 +1052,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); uint32_t nodeId; - if (DxcReflectionError err = PushNextNodeId( + if (ReflectionError err = PushNextNodeId( nodeId, Refl, SM, ASTCtx.getLangOpts(), ValDesc->getName(), ValDesc, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, uint32_t(Refl.Registers.size()))) @@ -1060,22 +1060,22 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, uint32_t arrayId; - if (DxcReflectionError err = + if (ReflectionError err = Refl.PushArray(arrayId, ArraySizeFlat, ArraySize)) return err; uint32_t bufferId = 0; D3D_CBUFFER_TYPE bufferType = - DxcHLSLReflectionData::GetBufferType(inputType.RegisterType); + ReflectionData::GetBufferType(inputType.RegisterType); if (bufferType != D3D_CT_INTERFACE_POINTERS) { bufferId = uint32_t(Refl.Buffers.size()); Refl.Buffers.push_back({bufferType, nodeId}); } - DxcHLSLRegister regD3D12; + ReflectionShaderResource regD3D12; - if (DxcReflectionError err = DxcHLSLRegister::Initialize( + if (ReflectionError err = ReflectionShaderResource::Initialize( regD3D12, inputType.RegisterType, ArraySizeFlat, uint32_t(inputType.RegisterFlags), inputType.TextureValue, inputType.TextureDimension, nodeId, arrayId, bufferId)) @@ -1112,13 +1112,13 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, uint32_t typeId; - if (DxcReflectionError err = + if (ReflectionError err = GenerateTypeInfo(typeId, ASTCtx, Refl, innerType, DefaultRowMaj)) return err; SourceRange sourceRange = ValDesc->getSourceRange(); - if (DxcReflectionError err = PushNextNodeId( + if (ReflectionError err = PushNextNodeId( nodeId, Refl, SM, ASTCtx.getLangOpts(), isListType ? "$Element" : ValDesc->getName(), nullptr, D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, typeId, &sourceRange)) @@ -1128,13 +1128,13 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, } } - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } template -[[nodiscard]] DxcReflectionError +[[nodiscard]] ReflectionError RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, - DxcHLSLReflectionData &Refl, const T &Decls, bool DefaultRowMaj, + ReflectionData &Refl, const T &Decls, bool DefaultRowMaj, uint32_t ParentId) { for (Decl *decl : Decls) { @@ -1146,13 +1146,13 @@ RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, const std::string &name = valDecl->getName(); uint32_t typeId; - if (DxcReflectionError err = + if (ReflectionError err = GenerateTypeInfo(typeId, ASTCtx, Refl, original, DefaultRowMaj)) return err; uint32_t nodeId; - if (DxcReflectionError err = + if (ReflectionError err = PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), name, decl, D3D12_HLSL_NODE_TYPE_VARIABLE, ParentId, typeId)) return err; @@ -1164,33 +1164,33 @@ RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, if (!recordDecl->isCompleteDefinition()) continue; - if (DxcReflectionError err = RecurseBuffer( + if (ReflectionError err = RecurseBuffer( ASTCtx, SM, Refl, recordDecl->fields(), DefaultRowMaj, nodeId)) return err; } } - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } -[[nodiscard]] DxcReflectionError +[[nodiscard]] ReflectionError RegisterBuffer(uint32_t &bufferId, ASTContext &ASTCtx, - DxcHLSLReflectionData &Refl, const SourceManager &SM, + ReflectionData &Refl, const SourceManager &SM, DeclContext *Buffer, uint32_t NodeId, D3D_CBUFFER_TYPE Type, bool DefaultRowMaj) { if (Refl.Buffers.size() >= uint32_t(-1)) - return DXC_REFLECT_ERR("Buffer id out of bounds"); + return HLSL_REFL_ERR("Buffer id out of bounds"); bufferId = uint32_t(Refl.Buffers.size()); - if (DxcReflectionError err = RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), + if (ReflectionError err = RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), DefaultRowMaj, NodeId)) return err; Refl.Buffers.push_back({Type, NodeId}); - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } //DxilInterpolationMode.cpp but a little bit cleaned up @@ -1237,21 +1237,21 @@ static D3D_INTERPOLATION_MODE GetInterpolationMode(Decl *decl) { return modes[mask]; } -[[nodiscard]] static DxcReflectionError +[[nodiscard]] static ReflectionError AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, - DxcHLSLReflectionData &Refl, + ReflectionData &Refl, const SourceManager &SM, uint32_t ParentNodeId, bool DefaultRowMaj) { uint32_t typeId; - if (DxcReflectionError err = + if (ReflectionError err = GenerateTypeInfo(typeId, ASTCtx, Refl, Type, DefaultRowMaj)) return err; uint32_t nodeId; - if (DxcReflectionError err = + if (ReflectionError err = PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), Decl && dyn_cast(Decl) ? dyn_cast(Decl)->getName() @@ -1276,22 +1276,22 @@ AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, } Refl.Parameters.push_back( - DxcHLSLParameter{typeId, nodeId, uint8_t(interpolationMode), uint8_t(flags)}); + ReflectionFunctionParameter{typeId, nodeId, uint8_t(interpolationMode), uint8_t(flags)}); - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } -[[nodiscard]] static DxcReflectionError RecursiveReflectBody( +[[nodiscard]] static ReflectionError RecursiveReflectBody( Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, - const SourceManager &SM, DxcHLSLReflectionData &Refl, + const SourceManager &SM, ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls, const LangOptions &LangOpts, bool SkipNextCompound = false); -[[nodiscard]] static DxcReflectionError GenerateStatement( +[[nodiscard]] static ReflectionError GenerateStatement( ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, - DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, + ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls, const LangOptions &LangOpts, D3D12_HLSL_NODE_TYPE Type, @@ -1303,24 +1303,24 @@ AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, const SourceRange &sourceRange = Self->getSourceRange(); uint32_t nodeId; - if (DxcReflectionError err = + if (ReflectionError err = PushNextNodeId(nodeId, Refl, SM, LangOpts, "", nullptr, Type, ParentNodeId, loc, &sourceRange, &FwdDecls)) return err; - Refl.Statements.push_back(DxcHLSLStatement()); + Refl.Statements.push_back(ReflectionScopeStmt()); if (VarDecl) { uint32_t typeId; - if (DxcReflectionError err = GenerateTypeInfo( + if (ReflectionError err = GenerateTypeInfo( typeId, ASTCtx, Refl, VarDecl->getType(), DefaultRowMaj)) return err; const SourceRange &sourceRange = VarDecl->getSourceRange(); uint32_t nextNodeId; - if (DxcReflectionError err = + if (ReflectionError err = PushNextNodeId(nextNodeId, Refl, SM, LangOpts, VarDecl->getName(), VarDecl, D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, typeId, &sourceRange, &FwdDecls)) @@ -1329,22 +1329,22 @@ AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, uint32_t start = uint32_t(Refl.Nodes.size()); - if (DxcReflectionError err = RecursiveReflectBody( + if (ReflectionError err = RecursiveReflectBody( Init, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls, LangOpts, true)) return err; - if (DxcReflectionError err = DxcHLSLStatement::Initialize( + if (ReflectionError err = ReflectionScopeStmt::Initialize( Refl.Statements[loc], nodeId, uint32_t(Refl.Nodes.size() - start), VarDecl, IfAndHasElse)) return err; - if (DxcReflectionError err = RecursiveReflectBody( + if (ReflectionError err = RecursiveReflectBody( Body, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, nodeId, DefaultRowMaj, FwdDecls, LangOpts, true)) return err; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } struct RecursiveStmtReflector : public StmtVisitor { @@ -1352,7 +1352,7 @@ struct RecursiveStmtReflector : public StmtVisitor { ASTContext &ASTCtx; DiagnosticsEngine &Diags; const SourceManager &SM; - DxcHLSLReflectionData &Refl; + ReflectionData &Refl; uint32_t AutoBindingSpace; uint32_t Depth; D3D12_HLSL_REFLECTION_FEATURE Features; @@ -1362,10 +1362,10 @@ struct RecursiveStmtReflector : public StmtVisitor { const LangOptions &LangOpts; bool SkipNextCompound; - DxcReflectionError LastError = DxcReflectionSuccess; + ReflectionError LastError = ReflectionErrorSuccess; RecursiveStmtReflector(ASTContext &ASTCtx, DiagnosticsEngine &Diags, - const SourceManager &SM, DxcHLSLReflectionData &Refl, + const SourceManager &SM, ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, @@ -1376,13 +1376,13 @@ struct RecursiveStmtReflector : public StmtVisitor { ParentNodeId(ParentNodeId), DefaultRowMaj(DefaultRowMaj), FwdDecls(FwdDecls), LangOpts(LangOpts), SkipNextCompound(SkipNextCompound) {} - [[nodiscard]] DxcReflectionError TraverseStmt(Stmt *S) { + [[nodiscard]] ReflectionError TraverseStmt(Stmt *S) { if (LastError) return LastError; if (!S) - return DxcReflectionSuccess; + return ReflectionErrorSuccess; while (AttributedStmt *AS = dyn_cast(S)) S = AS->getSubStmt(); @@ -1437,7 +1437,7 @@ struct RecursiveStmtReflector : public StmtVisitor { const SourceRange &sourceRange = Do->getSourceRange(); uint32_t scopeNode; - if (DxcReflectionError err = PushNextNodeId( + if (ReflectionError err = PushNextNodeId( scopeNode, Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_DO, ParentNodeId, 0, &sourceRange, &FwdDecls)) { LastError = err; @@ -1471,7 +1471,7 @@ struct RecursiveStmtReflector : public StmtVisitor { uint32_t scopeNode = ParentNodeId; if (!SkipNextCompound) - if (DxcReflectionError err = + if (ReflectionError err = PushNextNodeId(scopeNode, Refl, SM, LangOpts, "", nullptr, D3D12_HLSL_NODE_TYPE_SCOPE, ParentNodeId, 0, &sourceRange, &FwdDecls)) { @@ -1480,7 +1480,7 @@ struct RecursiveStmtReflector : public StmtVisitor { } for (Stmt *child : C->body()) - if (DxcReflectionError err = RecursiveReflectBody( + if (ReflectionError err = RecursiveReflectBody( child, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, scopeNode, DefaultRowMaj, FwdDecls, LangOpts)) { LastError = err; @@ -1497,7 +1497,7 @@ struct RecursiveStmtReflector : public StmtVisitor { if (VarDecl *varDecl = dyn_cast(D)) { uint32_t typeId; - if (DxcReflectionError err = GenerateTypeInfo( + if (ReflectionError err = GenerateTypeInfo( typeId, ASTCtx, Refl, varDecl->getType(), DefaultRowMaj)) { LastError = err; return; @@ -1506,7 +1506,7 @@ struct RecursiveStmtReflector : public StmtVisitor { const SourceRange &sourceRange = varDecl->getSourceRange(); uint32_t nodeId; - if (DxcReflectionError err = PushNextNodeId(nodeId, Refl, SM, LangOpts, varDecl->getName(), varDecl, + if (ReflectionError err = PushNextNodeId(nodeId, Refl, SM, LangOpts, varDecl->getName(), varDecl, D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId, &sourceRange, &FwdDecls)) { LastError = err; return; @@ -1516,10 +1516,10 @@ struct RecursiveStmtReflector : public StmtVisitor { } }; -[[nodiscard]] static DxcReflectionError +[[nodiscard]] static ReflectionError RecursiveReflectBody(Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, - DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, + ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls, @@ -1530,10 +1530,10 @@ RecursiveReflectBody(Stmt *Statement, ASTContext &ASTCtx, return Reflector.TraverseStmt(Statement); } -[[nodiscard]] static DxcReflectionError +[[nodiscard]] static ReflectionError RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, - DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, + ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls); @@ -1544,7 +1544,7 @@ class RecursiveReflector : public DeclVisitor { ASTContext &ASTCtx; const SourceManager &SM; DiagnosticsEngine &Diags; - DxcHLSLReflectionData &Refl; + ReflectionData &Refl; uint32_t AutoBindingSpace; uint32_t Depth; D3D12_HLSL_REFLECTION_FEATURE Features; @@ -1552,13 +1552,13 @@ class RecursiveReflector : public DeclVisitor { bool DefaultRowMaj; std::unordered_map &FwdDecls; - DxcReflectionError LastError = DxcReflectionSuccess; + ReflectionError LastError = ReflectionErrorSuccess; - [[nodiscard]] DxcReflectionError PushVariable(ValueDecl *VD, + [[nodiscard]] ReflectionError PushVariable(ValueDecl *VD, D3D12_HLSL_NODE_TYPE NodeType) { uint32_t typeId; - if (DxcReflectionError err = GenerateTypeInfo(typeId, ASTCtx, Refl, + if (ReflectionError err = GenerateTypeInfo(typeId, ASTCtx, Refl, VD->getType(), DefaultRowMaj)) return err; @@ -1571,7 +1571,7 @@ class RecursiveReflector : public DeclVisitor { RecursiveReflector(const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, DiagnosticsEngine &Diags, - DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, + ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls) @@ -1580,7 +1580,7 @@ class RecursiveReflector : public DeclVisitor { ParentNodeId(ParentNodeId), DefaultRowMaj(DefaultRowMaj), FwdDecls(FwdDecls){} - [[nodiscard]] DxcReflectionError TraverseDeclContext() { + [[nodiscard]] ReflectionError TraverseDeclContext() { if (LastError) return LastError; @@ -1599,7 +1599,7 @@ class RecursiveReflector : public DeclVisitor { return LastError; } - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } void VisitDecl(Decl *D) {} @@ -1617,7 +1617,7 @@ class RecursiveReflector : public DeclVisitor { uint32_t nodeId; - if (DxcReflectionError err = + if (ReflectionError err = PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), CB->getName(), CB, D3D12_HLSL_NODE_TYPE_REGISTER, ParentNodeId, uint32_t(Refl.Registers.size()))) { @@ -1627,16 +1627,16 @@ class RecursiveReflector : public DeclVisitor { uint32_t bufferId; - if (DxcReflectionError err = + if (ReflectionError err = RegisterBuffer(bufferId, ASTCtx, Refl, SM, CB, nodeId, D3D_CT_CBUFFER, DefaultRowMaj)) { LastError = err; return; } - DxcHLSLRegister regD3D12; + ReflectionShaderResource regD3D12; - if (DxcReflectionError err = DxcHLSLRegister::Initialize( + if (ReflectionError err = ReflectionShaderResource::Initialize( regD3D12, D3D_SIT_CBUFFER, 1, uint32_t(D3D_SIF_USERPACKED), D3D_RESOURCE_RETURN_TYPE(0), D3D_SRV_DIMENSION_UNKNOWN, nodeId, uint32_t(-1), bufferId)) { @@ -1661,7 +1661,7 @@ class RecursiveReflector : public DeclVisitor { const FunctionDecl *definition = nullptr; uint32_t nodeId; - if (DxcReflectionError err = PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), FD->getName(), FD, + if (ReflectionError err = PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), FD->getName(), FD, D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, uint32_t(Refl.Functions.size()), nullptr, &FwdDecls)) { LastError = err; @@ -1672,16 +1672,16 @@ class RecursiveReflector : public DeclVisitor { return; bool hasDefinition = FD->hasBody(definition); - DxcHLSLFunction func; + ReflectionFunction func; - if (DxcReflectionError err = DxcHLSLFunction::Initialize(func, nodeId, FD->getNumParams(), + if (ReflectionError err = ReflectionFunction::Initialize(func, nodeId, FD->getNumParams(), !FD->getReturnType().getTypePtr()->isVoidType(), hasDefinition)) { LastError = err; return; } for (uint32_t i = 0; i < func.GetNumParameters(); ++i) - if (DxcReflectionError err = AddFunctionParameter( + if (ReflectionError err = AddFunctionParameter( ASTCtx, FD->getParamDecl(i)->getType(), FD->getParamDecl(i), Refl, SM, nodeId, DefaultRowMaj)) { LastError = err; @@ -1689,7 +1689,7 @@ class RecursiveReflector : public DeclVisitor { } if (func.HasReturn()) - if (DxcReflectionError err = + if (ReflectionError err = AddFunctionParameter(ASTCtx, FD->getReturnType(), nullptr, Refl, SM, nodeId, DefaultRowMaj)) { LastError = err; @@ -1707,7 +1707,7 @@ class RecursiveReflector : public DeclVisitor { if (!subStmt) continue; - if (DxcReflectionError err = RecursiveReflectBody(subStmt, ASTCtx, Diags, SM, Refl, AutoBindingSpace, + if (ReflectionError err = RecursiveReflectBody(subStmt, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth, Features, nodeId, DefaultRowMaj, FwdDecls, ASTCtx.getLangOpts())) { LastError = err; @@ -1727,7 +1727,7 @@ class RecursiveReflector : public DeclVisitor { uint32_t nodeId; - if (DxcReflectionError err = PushNextNodeId( + if (ReflectionError err = PushNextNodeId( nodeId, Refl, SM, ASTCtx.getLangOpts(), ED->getName(), ED, D3D12_HLSL_NODE_TYPE_ENUM, ParentNodeId, uint32_t(Refl.Enums.size()), nullptr, &FwdDecls)) { @@ -1742,7 +1742,7 @@ class RecursiveReflector : public DeclVisitor { uint32_t childNodeId; - if (DxcReflectionError err = PushNextNodeId( + if (ReflectionError err = PushNextNodeId( childNodeId, Refl, SM, ASTCtx.getLangOpts(), enumValue->getName(), enumValue, D3D12_HLSL_NODE_TYPE_ENUM_VALUE, nodeId, uint32_t(Refl.EnumValues.size()))) { @@ -1755,7 +1755,7 @@ class RecursiveReflector : public DeclVisitor { } if (Refl.EnumValues.size() >= uint32_t(1 << 30)) { - LastError = DXC_REFLECT_ERR("Enum values overflow"); + LastError = HLSL_REFL_ERR("Enum values overflow"); return; } @@ -1796,7 +1796,7 @@ class RecursiveReflector : public DeclVisitor { return; uint32_t typeId; - if (DxcReflectionError err = GenerateTypeInfo( + if (ReflectionError err = GenerateTypeInfo( typeId, ASTCtx, Refl, TD->getUnderlyingType(), DefaultRowMaj)) { LastError = err; return; @@ -1908,7 +1908,7 @@ class RecursiveReflector : public DeclVisitor { uint32_t typeId = 0; if (isDefinition) - if (DxcReflectionError err = GenerateTypeInfo( + if (ReflectionError err = GenerateTypeInfo( typeId, ASTCtx, Refl, RD->getASTContext().getRecordType(RD), DefaultRowMaj)) { LastError = err; @@ -1916,7 +1916,7 @@ class RecursiveReflector : public DeclVisitor { } uint32_t self; - if (DxcReflectionError err = PushNextNodeId( + if (ReflectionError err = PushNextNodeId( self, Refl, SM, ASTCtx.getLangOpts(), RD->getName(), RD, type, ParentNodeId, typeId, nullptr, &FwdDecls)) { LastError = err; @@ -1942,7 +1942,7 @@ class RecursiveReflector : public DeclVisitor { return; uint32_t nodeId; - if (DxcReflectionError err = PushNextNodeId( + if (ReflectionError err = PushNextNodeId( nodeId, Refl, SM, ASTCtx.getLangOpts(), ND->getName(), ND, D3D12_HLSL_NODE_TYPE_NAMESPACE, ParentNodeId, 0)) { LastError = err; @@ -1966,10 +1966,10 @@ class RecursiveReflector : public DeclVisitor { }*/ }; -[[nodiscard]] static DxcReflectionError +[[nodiscard]] static ReflectionError RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, DiagnosticsEngine &Diags, const SourceManager &SM, - DxcHLSLReflectionData &Refl, uint32_t AutoBindingSpace, + ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls) { @@ -1979,8 +1979,8 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, return Reflector.TraverseDeclContext(); } -[[nodiscard]] DxcReflectionError DxcHLSLReflectionDataFromAST( - DxcHLSLReflectionData &Result, +[[nodiscard]] ReflectionError DxcHLSLReflectionDataFromAST( + ReflectionData &Result, CompilerInstance &Compiler, TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, @@ -1998,7 +1998,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, Result.StringsToId[""] = 0; Result.NodeSymbols.push_back({}); - if (DxcReflectionError err = DxcHLSLNodeSymbol::Initialize( + if (ReflectionError err = ReflectionNodeSymbol::Initialize( Result.NodeSymbols[0], 0, 0, 0, 0, 0, 0)) { llvm::errs() << "DxcHLSLReflectionDataFromAST: Failed to add root symbol: " << err; @@ -2008,7 +2008,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, } Result.Nodes.push_back({}); - if (DxcReflectionError err = DxcHLSLNode::Initialize( + if (ReflectionError err = ReflectionNode::Initialize( Result.Nodes[0], D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, 0, 0, 0xFFFF, 0, uint16_t(-1))) { llvm::errs() << "DxcHLSLReflectionDataFromAST: Failed to add root node: " @@ -2019,7 +2019,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, std::unordered_map fwdDecls; - if (DxcReflectionError err = RecursiveReflectHLSL( + if (ReflectionError err = RecursiveReflectHLSL( Ctx, Compiler.getASTContext(), Diags, SM, Result, AutoBindingSpace, 0, Features, 0, DefaultRowMaj, fwdDecls)) { llvm::errs() << "DxcHLSLReflectionDataFromAST: Failed: " << err; @@ -2027,7 +2027,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, return err; } - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } } // namespace hlsl diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 6fd07f694a..9b31bef27a 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -51,7 +51,7 @@ using namespace hlsl; namespace hlsl { -[[nodiscard]] DxcReflectionError DxcHLSLReflectionDataFromAST(DxcHLSLReflectionData &Result, +[[nodiscard]] ReflectionError DxcHLSLReflectionDataFromAST(ReflectionData &Result, clang::CompilerInstance &Compiler, clang::TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, @@ -170,16 +170,16 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { CHLSLReflectionType *m_pBaseClass; std::vector m_Interfaces; - const DxcHLSLReflectionData *m_Data; + const ReflectionData *m_Data; uint32_t m_TypeId; uint32_t m_ElementsUnderlying; uint32_t m_ElementsDisplay; D3D12_ARRAY_DESC m_ArrayDescUnderlying; D3D12_ARRAY_DESC m_ArrayDescDisplay; - void InitializeArray(const DxcHLSLReflectionData &Data, + void InitializeArray(const ReflectionData &Data, D3D12_ARRAY_DESC &desc, uint32_t &elements, - const DxcHLSLArrayOrElements &arrElem) { + const ReflectionArrayOrElements &arrElem) { if (arrElem.IsArray()) { @@ -187,7 +187,7 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { if (arrElem.IsMultiDimensionalArray()) { - const DxcHLSLArray &arr = + const ReflectionArray &arr = Data.Arrays[arrElem.GetMultiDimensionalArrayId()]; desc.ArrayDims = arr.ArrayElem(); @@ -242,7 +242,7 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { } HRESULT Initialize( - const DxcHLSLReflectionData &Data, uint32_t TypeId, + const ReflectionData &Data, uint32_t TypeId, std::vector &Types /* Only access < TypeId*/) { m_TypeId = TypeId; @@ -250,7 +250,7 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { m_ElementsDisplay = 0; m_Data = &Data; - const DxcHLSLType &type = Data.Types[TypeId]; + const ReflectionVariableType &type = Data.Types[TypeId]; ZeroMemoryToOut(&m_ArrayDescUnderlying); ZeroMemoryToOut(&m_ArrayDescDisplay); @@ -261,7 +261,7 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { bool hasNames = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; if (hasNames) { - DxcHLSLTypeSymbol sym = Data.TypeSymbols[TypeId]; + ReflectionVariableTypeSymbol sym = Data.TypeSymbols[TypeId]; m_NameUnderlying = Data.Strings[sym.UnderlyingNameId]; m_NameDisplay = Data.Strings[sym.DisplayNameId]; InitializeArray(Data, m_ArrayDescDisplay, m_ElementsDisplay, sym.DisplayArray); @@ -305,7 +305,7 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { IFR(ZeroMemoryToOut(pDesc)); - const DxcHLSLType &type = m_Data->Types[m_TypeId]; + const ReflectionVariableType &type = m_Data->Types[m_TypeId]; *pDesc = D3D12_SHADER_TYPE_DESC { @@ -327,7 +327,7 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { IFR(ZeroMemoryToOut(pDesc)); - const DxcHLSLType &type = m_Data->Types[m_TypeId]; + const ReflectionVariableType &type = m_Data->Types[m_TypeId]; GetDesc(&pDesc->Desc); pDesc->DisplayName = m_NameDisplay.c_str(); @@ -399,13 +399,13 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { class CHLSLFunctionParameter final : public ID3D12FunctionParameterReflection { protected: - const DxcHLSLReflectionData *m_Data = nullptr; + const ReflectionData *m_Data = nullptr; uint32_t m_NodeId = 0; public: CHLSLFunctionParameter() = default; - void Initialize(const DxcHLSLReflectionData &Data, uint32_t NodeId) { + void Initialize(const ReflectionData &Data, uint32_t NodeId) { m_Data = &Data; m_NodeId = NodeId; } @@ -414,7 +414,7 @@ class CHLSLFunctionParameter final : public ID3D12FunctionParameterReflection { IFR(ZeroMemoryToOut(pDesc)); - const DxcHLSLNode &node = m_Data->Nodes[m_NodeId]; + const ReflectionNode &node = m_Data->Nodes[m_NodeId]; LPCSTR semanticName = node.GetSemanticId() == uint32_t(-1) @@ -426,8 +426,8 @@ class CHLSLFunctionParameter final : public ID3D12FunctionParameterReflection { ? m_Data->Strings[m_Data->NodeSymbols[m_NodeId].GetNameId()].c_str() : ""; - const DxcHLSLParameter ¶m = m_Data->Parameters[node.GetLocalId()]; - const DxcHLSLType &type = m_Data->Types[param.TypeId]; + const ReflectionFunctionParameter ¶m = m_Data->Parameters[node.GetLocalId()]; + const ReflectionVariableType &type = m_Data->Types[param.TypeId]; *pDesc = D3D12_PARAMETER_DESC{name, @@ -484,7 +484,7 @@ class CHLSLReflectionVariable final : public ID3D12ShaderReflectionVariable { class CHLSLReflectionConstantBuffer final : public ID3D12ShaderReflectionConstantBuffer { protected: - const DxcHLSLReflectionData *m_Data; + const ReflectionData *m_Data; uint32_t m_ChildCount; D3D_CBUFFER_TYPE m_BufferType; std::vector m_Variables; @@ -505,7 +505,7 @@ class CHLSLReflectionConstantBuffer final std::swap(m_VariablesByName, other.m_VariablesByName); } - void Initialize(const DxcHLSLReflectionData &Data, uint32_t NodeId, + void Initialize(const ReflectionData &Data, uint32_t NodeId, const std::unordered_map> &ChildrenNonRecursive, CHLSLReflectionConstantBuffer *ConstantBuffer, @@ -514,14 +514,14 @@ class CHLSLReflectionConstantBuffer final if (NodeId >= Data.Nodes.size()) return; - const DxcHLSLNode &node = Data.Nodes[NodeId]; + const ReflectionNode &node = Data.Nodes[NodeId]; if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER) return; const std::vector &children = ChildrenNonRecursive.at(NodeId); - const DxcHLSLRegister ® = Data.Registers[node.GetLocalId()]; + const ReflectionShaderResource ® = Data.Registers[node.GetLocalId()]; if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { @@ -570,7 +570,7 @@ class CHLSLReflectionConstantBuffer final } //$Globals (only if the global scope contains any VARIABLE node) - void InitializeGlobals(const DxcHLSLReflectionData &Data, + void InitializeGlobals(const ReflectionData &Data, const std::vector &Globals, CHLSLReflectionConstantBuffer *ConstantBuffer, std::vector &Types) { @@ -588,7 +588,7 @@ class CHLSLReflectionConstantBuffer final uint32_t childId = Globals[i]; - const DxcHLSLNode &node = Data.Nodes[childId]; + const ReflectionNode &node = Data.Nodes[childId]; std::string name; @@ -649,7 +649,7 @@ ID3D12ShaderReflectionConstantBuffer *CHLSLReflectionVariable::GetBuffer() { struct DxcHLSLReflection : public IDxcHLSLReflection { - DxcHLSLReflectionData Data{}; + ReflectionData Data{}; std::vector ChildCountsNonRecursive; std::unordered_map> ChildrenNonRecursive; @@ -695,7 +695,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { for (uint32_t i = 0; i < uint32_t(Data.Nodes.size()); ++i) { - const DxcHLSLNode &node = Data.Nodes[i]; + const ReflectionNode &node = Data.Nodes[i]; if (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_VARIABLE && !node.GetParentId()) @@ -752,7 +752,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { for (uint32_t j = 0; j < node.GetChildCount(); ++j) { - const DxcHLSLNode &nodej = Data.Nodes[i + 1 + j]; + const ReflectionNode &nodej = Data.Nodes[i + 1 + j]; // Filter out definitions that were previously fwd declared // And resolve fwd declarations @@ -796,7 +796,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { Data, globalVars, &ConstantBuffers[Data.Buffers.size()], Types); } - DxcHLSLReflection(DxcHLSLReflectionData &&moved) : Data(moved) { + DxcHLSLReflection(ReflectionData &&moved) : Data(moved) { Finalize(); } @@ -849,7 +849,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (ResourceIndex >= Data.Registers.size()) return E_INVALIDARG; - const DxcHLSLRegister ® = Data.Registers[ResourceIndex]; + const ReflectionShaderResource ® = Data.Registers[ResourceIndex]; LPCSTR name = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO @@ -861,7 +861,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (reg.GetArrayId() != uint32_t(-1)) { - const DxcHLSLArray &arr = Data.Arrays[reg.GetArrayId()]; + const ReflectionArray &arr = Data.Arrays[reg.GetArrayId()]; pDesc->ArrayInfo.ArrayDims = arr.ArrayElem(); @@ -899,7 +899,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (EnumIndex >= NonFwdIds[int(FwdDeclType::ENUM)].size()) return E_INVALIDARG; - const DxcHLSLEnumDesc &enm = + const ReflectionEnumeration &enm = Data.Enums[NonFwdIds[int(FwdDeclType::ENUM)][EnumIndex]]; LPCSTR name = @@ -922,8 +922,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (EnumIndex >= NonFwdIds[int(FwdDeclType::ENUM)].size()) return E_INVALIDARG; - const DxcHLSLEnumDesc &enm = Data.Enums[NonFwdIds[int(FwdDeclType::ENUM)][EnumIndex]]; - const DxcHLSLNode &parent = Data.Nodes[enm.NodeId]; + const ReflectionEnumeration &enm = Data.Enums[NonFwdIds[int(FwdDeclType::ENUM)][EnumIndex]]; + const ReflectionNode &parent = Data.Nodes[enm.NodeId]; if (ValueIndex >= parent.GetChildCount()) return E_INVALIDARG; @@ -933,7 +933,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { ? Data.Strings[Data.NodeSymbols[enm.NodeId].GetNameId()].c_str() : ""; - const DxcHLSLNode &node = Data.Nodes[enm.NodeId + 1 + ValueIndex]; + const ReflectionNode &node = Data.Nodes[enm.NodeId + 1 + ValueIndex]; *pValueDesc = D3D12_HLSL_ENUM_VALUE{name, Data.EnumValues[node.GetLocalId()].Value}; @@ -950,12 +950,12 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (NodeId >= Data.Nodes.size()) return E_INVALIDARG; - const DxcHLSLNode &node = Data.Nodes[NodeId]; + const ReflectionNode &node = Data.Nodes[NodeId]; if (Index >= node.GetAnnotationCount()) return E_INVALIDARG; - const DxcHLSLAnnotation &annotation = + const ReflectionAnnotation &annotation = Data.Annotations[node.GetAnnotationStart() + Index]; *pAnnotation = D3D12_HLSL_ANNOTATION{ @@ -974,7 +974,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (FunctionIndex >= NonFwdIds[int(FwdDeclType::FUNCTION)].size()) return E_INVALIDARG; - const DxcHLSLFunction &func = + const ReflectionFunction &func = Data.Functions[NonFwdIds[int(FwdDeclType::FUNCTION)][FunctionIndex]]; LPCSTR name = @@ -1001,7 +1001,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { ? Data.Strings[Data.NodeSymbols[NodeId].GetNameId()].c_str() : ""; - const DxcHLSLNode &node = Data.Nodes[NodeId]; + const ReflectionNode &node = Data.Nodes[NodeId]; uint32_t localId = node.GetLocalId(); uint32_t parentId = node.GetParentId(); @@ -1096,7 +1096,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (FunctionIndex >= Data.Functions.size()) return nullptr; - const DxcHLSLFunction &func = Data.Functions[FunctionIndex]; + const ReflectionFunction &func = Data.Functions[FunctionIndex]; if (ParameterIndex == D3D_RETURN_PARAMETER_INDEX) { @@ -1167,7 +1167,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { if (NodeId >= Data.Nodes.size()) return E_INVALIDARG; - const DxcHLSLNodeSymbol &nodeSymbol = Data.NodeSymbols[NodeId]; + const ReflectionNodeSymbol &nodeSymbol = Data.NodeSymbols[NodeId]; *pDesc = D3D12_HLSL_NODE_SYMBOL{ Data.Strings[Data.Sources[nodeSymbol.GetFileSourceId()]].c_str(), @@ -1226,7 +1226,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { UINT nodeId; IFR(GetNodeByName(Name, &nodeId)); - const DxcHLSLNode &node = Data.Nodes[nodeId]; + const ReflectionNode &node = Data.Nodes[nodeId]; if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER) return E_INVALIDARG; @@ -1242,7 +1242,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { UINT nodeId; IFR(GetNodeByName(Name, &nodeId)); - const DxcHLSLNode &node = Data.Nodes[nodeId]; + const ReflectionNode &node = Data.Nodes[nodeId]; if (node.IsFwdDeclare()) return E_UNEXPECTED; @@ -1262,7 +1262,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { UINT nodeId; IFR(GetNodeByName(Name, &nodeId)); - const DxcHLSLNode &node = Data.Nodes[nodeId]; + const ReflectionNode &node = Data.Nodes[nodeId]; if (node.IsFwdDeclare()) return E_UNEXPECTED; @@ -1294,7 +1294,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { UINT nodeId; IFR(GetNodeByName(Name, &nodeId)); - const DxcHLSLNode &node = Data.Nodes[nodeId]; + const ReflectionNode &node = Data.Nodes[nodeId]; if (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION) return E_INVALIDARG; @@ -1554,7 +1554,7 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, UINT32 defineCount, std::string &warnings, std::string &result, dxcutil::DxcArgsFileSystem *msfPtr, - DxcHLSLReflectionData &reflection) { + ReflectionData &reflection) { raw_string_ostream o(result); raw_string_ostream w(warnings); @@ -1596,9 +1596,9 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, if (!opts.ReflOpt.DisableSymbols) reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - DxcHLSLReflectionData refl; + ReflectionData refl; - if (DxcReflectionError err = DxcHLSLReflectionDataFromAST( + if (ReflectionError err = DxcHLSLReflectionDataFromAST( refl, astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, reflectMask, opts.DefaultRowMajor)) { printf("DxcHLSLReflectionDataFromAST failed %s\n", err.err); //TODO: @@ -1612,9 +1612,9 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, std::vector bytes; refl.Dump(bytes); - DxcHLSLReflectionData deserialized; + ReflectionData deserialized; - if (DxcReflectionError err = deserialized.Deserialize(bytes, true)) { + if (ReflectionError err = deserialized.Deserialize(bytes, true)) { printf("Deserialize failed %s\n", err.err); // TODO: return E_FAIL; } @@ -1634,9 +1634,9 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, refl.Dump(bytes); - DxcHLSLReflectionData deserialized2; + ReflectionData deserialized2; - if (DxcReflectionError err = deserialized2.Deserialize(bytes, true)) { + if (ReflectionError err = deserialized2.Deserialize(bytes, true)) { printf("Deserialize failed %s\n", err.err); // TODO: return E_FAIL; } @@ -1753,7 +1753,7 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { std::unique_ptr pRemap( new ASTUnit::RemappedFile(fName, pBuffer.release())); - DxcHLSLReflectionData reflection; + ReflectionData reflection; std::string errors; std::string rewrite; @@ -1786,9 +1786,9 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { data->GetBufferSize()); try { - DxcHLSLReflectionData deserial; + ReflectionData deserial; - if (DxcReflectionError err = deserial.Deserialize(bytes, true)) + if (ReflectionError err = deserial.Deserialize(bytes, true)) return E_FAIL; *ppReflection = new DxcHLSLReflection(std::move(deserial)); diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index dfecc1dd03..2daee0631b 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // // -// DxcReflection.cpp // +// DxcReflectionContainer.cpp // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // @@ -16,24 +16,24 @@ namespace hlsl { -[[nodiscard]] DxcReflectionError DxcHLSLReflectionData::RegisterString( +[[nodiscard]] ReflectionError ReflectionData::RegisterString( uint32_t &StringId, const std::string &Name, bool IsNonDebug) { if (Name.size() >= 32768) - return DXC_REFLECT_ERR("Strings are limited to 32767"); + return HLSL_REFL_ERR("Strings are limited to 32767"); if (IsNonDebug) { if (StringsNonDebug.size() >= uint32_t(-1)) - return DXC_REFLECT_ERR("Strings overflow"); + return HLSL_REFL_ERR("Strings overflow"); auto it = StringsToIdNonDebug.find(Name); if (it != StringsToIdNonDebug.end()) { StringId = it->second; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } uint32_t stringId = uint32_t(StringsNonDebug.size()); @@ -41,17 +41,17 @@ namespace hlsl { StringsNonDebug.push_back(Name); StringsToIdNonDebug[Name] = stringId; StringId = stringId; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } if (Strings.size() >= uint32_t(-1)) - return DXC_REFLECT_ERR("Strings overflow"); + return HLSL_REFL_ERR("Strings overflow"); auto it = StringsToId.find(Name); if (it != StringsToId.end()) { StringId = it->second; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } uint32_t stringId = uint32_t(Strings.size()); @@ -59,20 +59,20 @@ namespace hlsl { Strings.push_back(Name); StringsToId[Name] = stringId; StringId = stringId; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } -[[nodiscard]] DxcReflectionError -DxcHLSLReflectionData::PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, +[[nodiscard]] ReflectionError +ReflectionData::PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, const std::vector &ArraySize) { if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) { ArrayId = uint32_t(-1); - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } if (Arrays.size() >= uint32_t((1u << 31) - 1)) - return DXC_REFLECT_ERR("Arrays would overflow"); + return HLSL_REFL_ERR("Arrays would overflow"); uint32_t arrayId = uint32_t(Arrays.size()); @@ -80,7 +80,7 @@ DxcHLSLReflectionData::PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, uint32_t numArrayElements = std::min(size_t(32), ArraySize.size()); if (ArraySizes.size() + numArrayElements >= ((1u << 26) - 1)) - return DXC_REFLECT_ERR("Array elements would overflow"); + return HLSL_REFL_ERR("Array elements would overflow"); for (uint32_t i = 0; i < ArraySize.size() && i < 8; ++i) { @@ -94,32 +94,32 @@ DxcHLSLReflectionData::PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, ArraySizes.push_back(arraySize); } - DxcHLSLArray arr; + ReflectionArray arr; - if (DxcReflectionError err = - DxcHLSLArray::Initialize(arr, numArrayElements, arrayCountStart)) + if (ReflectionError err = + ReflectionArray::Initialize(arr, numArrayElements, arrayCountStart)) return err; for (uint32_t i = 0; i < Arrays.size(); ++i) if (Arrays[i] == arr) { ArrayId = i; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } Arrays.push_back(arr); ArrayId = arrayId; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } -[[nodiscard]] DxcReflectionError -DxcHLSLReflectionData::RegisterTypeList( +[[nodiscard]] ReflectionError +ReflectionData::RegisterTypeList( const std::vector &TypeIds, uint32_t &Offset, uint8_t &Len) { if (TypeIds.empty()) - return DxcReflectionSuccess; + return ReflectionErrorSuccess; if (TypeIds.size() >= uint8_t(-1)) - return DXC_REFLECT_ERR("Only allowing 256 types in a type list"); + return HLSL_REFL_ERR("Only allowing 256 types in a type list"); uint32_t i = 0; uint32_t j = uint32_t(TypeList.size()); @@ -152,7 +152,7 @@ DxcHLSLReflectionData::RegisterTypeList( uint32_t oldSiz = uint32_t(TypeList.size()); if (oldSiz + TypeIds.size() >= (1u << 24)) - return DXC_REFLECT_ERR("Only allowing 16Mi total interfaces"); + return HLSL_REFL_ERR("Only allowing 16Mi total interfaces"); TypeList.resize(oldSiz + TypeIds.size()); @@ -163,7 +163,7 @@ DxcHLSLReflectionData::RegisterTypeList( } Len = uint8_t(TypeIds.size()); - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } struct DxcHLSLHeader { @@ -280,23 +280,23 @@ void Append(std::vector &Bytes, uint64_t &Offset, } template >> -[[nodiscard]] DxcReflectionError Consume(const std::vector &Bytes, uint64_t &Offset, T &t) { +[[nodiscard]] ReflectionError Consume(const std::vector &Bytes, uint64_t &Offset, T &t) { static_assert(std::is_pod_v, "Consume only works on POD types"); SkipPadding(Offset); if (Offset + sizeof(T) > Bytes.size()) - return DXC_REFLECT_ERR("Couldn't consume; out of bounds!"); + return HLSL_REFL_ERR("Couldn't consume; out of bounds!"); std::memcpy(&t, &UnsafeCast(Bytes, Offset), sizeof(T)); Offset += sizeof(T); - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } template -[[nodiscard]] DxcReflectionError Consume(const std::vector &Bytes, +[[nodiscard]] ReflectionError Consume(const std::vector &Bytes, uint64_t &Offset, T *target, uint64_t Len) { @@ -305,16 +305,16 @@ template SkipPadding(Offset); if (Offset + sizeof(T) * Len > Bytes.size()) - return DXC_REFLECT_ERR("Couldn't consume; out of bounds!"); + return HLSL_REFL_ERR("Couldn't consume; out of bounds!"); std::memcpy(target, &UnsafeCast(Bytes, Offset), sizeof(T) * Len); Offset += sizeof(T) * Len; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } template -[[nodiscard]] DxcReflectionError Consume(const std::vector &Bytes, +[[nodiscard]] ReflectionError Consume(const std::vector &Bytes, uint64_t &Offset, std::vector &Vec, uint64_t Len) { Vec.resize(Len); @@ -322,7 +322,7 @@ template } template <> -[[nodiscard]] DxcReflectionError +[[nodiscard]] ReflectionError Consume(const std::vector &Bytes, uint64_t &Offset, std::vector &Vec, uint64_t Len) { Vec.resize(Len); @@ -330,49 +330,49 @@ Consume(const std::vector &Bytes, uint64_t &Offset, for (uint64_t i = 0; i < Len; ++i) { if (Offset >= Bytes.size()) - return DXC_REFLECT_ERR("Couldn't consume string len; out of bounds!"); + return HLSL_REFL_ERR("Couldn't consume string len; out of bounds!"); uint16_t ourLen = uint8_t(Bytes.at(Offset++)); if (ourLen >> 7) { if (Offset >= Bytes.size()) - return DXC_REFLECT_ERR("Couldn't consume string len; out of bounds!"); + return HLSL_REFL_ERR("Couldn't consume string len; out of bounds!"); ourLen &= ~(1 << 7); ourLen |= uint16_t(Bytes.at(Offset++)) << 7; } if (Offset + ourLen > Bytes.size()) - return DXC_REFLECT_ERR("Couldn't consume string len; out of bounds!"); + return HLSL_REFL_ERR("Couldn't consume string len; out of bounds!"); Vec[i].resize(ourLen); std::memcpy(Vec[i].data(), Bytes.data() + Offset, ourLen); Offset += ourLen; } - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } template -[[nodiscard]] DxcReflectionError Consume(const std::vector &Bytes, +[[nodiscard]] ReflectionError Consume(const std::vector &Bytes, uint64_t &Offset, std::vector &Vec, uint64_t Len, std::vector &Vec2, uint64_t Len2, args&... arg) { - if (DxcReflectionError err = Consume(Bytes, Offset, Vec, Len)) + if (ReflectionError err = Consume(Bytes, Offset, Vec, Len)) return err; - if (DxcReflectionError err = Consume(Bytes, Offset, Vec2, Len2, arg...)) + if (ReflectionError err = Consume(Bytes, Offset, Vec2, Len2, arg...)) return err; - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } static constexpr uint32_t DxcReflectionDataMagic = DXC_FOURCC('D', 'H', 'R', 'D'); static constexpr uint16_t DxcReflectionDataVersion = 0; -void DxcHLSLReflectionData::StripSymbols() { +void ReflectionData::StripSymbols() { Strings.clear(); StringsToId.clear(); Sources.clear(); @@ -386,10 +386,10 @@ void DxcHLSLReflectionData::StripSymbols() { Features &= ~D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; } -void RecurseNameGenerationType(DxcHLSLReflectionData &Refl, uint32_t TypeId, +void RecurseNameGenerationType(ReflectionData &Refl, uint32_t TypeId, uint32_t LocalId, const std::string &Parent) { - const DxcHLSLType &type = Refl.Types[TypeId]; + const ReflectionVariableType &type = Refl.Types[TypeId]; if (type.GetClass() == D3D_SVC_STRUCT) for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { @@ -405,11 +405,11 @@ void RecurseNameGenerationType(DxcHLSLReflectionData &Refl, uint32_t TypeId, } } -uint32_t RecurseNameGeneration(DxcHLSLReflectionData &Refl, uint32_t NodeId, +uint32_t RecurseNameGeneration(ReflectionData &Refl, uint32_t NodeId, uint32_t LocalId, const std::string &Parent, bool IsDot) { - DxcHLSLNode node = Refl.Nodes[NodeId]; + ReflectionNode node = Refl.Nodes[NodeId]; if (node.IsFwdDeclare() && node.IsFwdBckDefined()) { NodeId = node.GetFwdBck(); @@ -437,7 +437,7 @@ uint32_t RecurseNameGeneration(DxcHLSLReflectionData &Refl, uint32_t NodeId, if (isVar) { uint32_t typeId = node.GetLocalId(); - const DxcHLSLType &type = Refl.Types[typeId]; + const ReflectionVariableType &type = Refl.Types[typeId]; if (type.GetClass() == D3D_SVC_STRUCT) for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { @@ -456,7 +456,7 @@ uint32_t RecurseNameGeneration(DxcHLSLReflectionData &Refl, uint32_t NodeId, return node.GetChildCount(); } -bool DxcHLSLReflectionData::GenerateNameLookupTable() { +bool ReflectionData::GenerateNameLookupTable() { if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) || Nodes.empty()) return false; @@ -466,7 +466,7 @@ bool DxcHLSLReflectionData::GenerateNameLookupTable() { return true; } -void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { +void ReflectionData::Dump(std::vector &Bytes) const { uint64_t toReserve = sizeof(DxcHLSLHeader); @@ -499,7 +499,7 @@ void DxcHLSLReflectionData::Dump(std::vector &Bytes) const { TypeSymbols, Buffers, Parameters, Statements); } -D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { +D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { switch (Type) { @@ -521,7 +521,7 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { } } -[[nodiscard]] DxcReflectionError DxcHLSLReflectionData::Deserialize(const std::vector &Bytes, +[[nodiscard]] ReflectionError ReflectionData::Deserialize(const std::vector &Bytes, bool MakeNameLookupTable) { @@ -529,14 +529,14 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { uint64_t off = 0; DxcHLSLHeader header; - if (DxcReflectionError err = Consume(Bytes, off, header)) + if (ReflectionError err = Consume(Bytes, off, header)) return err; if (header.MagicNumber != DxcReflectionDataMagic) - return DXC_REFLECT_ERR("Invalid magic number"); + return HLSL_REFL_ERR("Invalid magic number"); if (header.Version != DxcReflectionDataVersion) - return DXC_REFLECT_ERR("Unrecognized version number"); + return HLSL_REFL_ERR("Unrecognized version number"); Features = header.Features; @@ -544,13 +544,13 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; if (!hasSymbolInfo && (header.Sources || header.Strings)) - return DXC_REFLECT_ERR("Sources are invalid without symbols"); + return HLSL_REFL_ERR("Sources are invalid without symbols"); uint32_t nodeSymbolCount = hasSymbolInfo ? header.Nodes : 0; uint32_t memberSymbolCount = hasSymbolInfo ? header.Members : 0; uint32_t typeSymbolCount = hasSymbolInfo ? header.Types : 0; - if (DxcReflectionError err = Consume( + if (ReflectionError err = Consume( Bytes, off, Strings, header.Strings, StringsNonDebug, header.StringsNonDebug, Sources, header.Sources, Nodes, header.Nodes, NodeSymbols, nodeSymbolCount, Registers, header.Registers, Functions, @@ -565,33 +565,33 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { // Validation errors to prevent accessing invalid data if (off != Bytes.size()) - return DXC_REFLECT_ERR("Reflection info had unrecognized data on the back"); + return HLSL_REFL_ERR("Reflection info had unrecognized data on the back"); for(uint32_t i = 0; i < header.Sources; ++i) if (Sources[i] >= header.Strings) - return DXC_REFLECT_ERR("Source path out of bounds", i); + return HLSL_REFL_ERR("Source path out of bounds", i); std::vector validateChildren; for (uint32_t i = 0; i < header.Nodes; ++i) { - const DxcHLSLNode &node = Nodes[i]; + const ReflectionNode &node = Nodes[i]; if (hasSymbolInfo && (NodeSymbols[i].GetNameId() >= header.Strings || (NodeSymbols[i].GetFileSourceId() != uint16_t(-1) && NodeSymbols[i].GetFileSourceId() >= header.Sources))) - return DXC_REFLECT_ERR("Node points to invalid name or file name", i); + return HLSL_REFL_ERR("Node points to invalid name or file name", i); if (node.GetAnnotationStart() + node.GetAnnotationCount() > header.Annotations || node.GetNodeType() > D3D12_HLSL_NODE_TYPE_END || (i && node.GetParentId() >= i) || i + node.GetChildCount() > header.Nodes) - return DXC_REFLECT_ERR("Node is invalid", i); + return HLSL_REFL_ERR("Node is invalid", i); if (node.GetSemanticId() != uint32_t(-1) && node.GetSemanticId() >= header.StringsNonDebug) - return DXC_REFLECT_ERR("Node points to invalid semantic id", i); + return HLSL_REFL_ERR("Node points to invalid semantic id", i); uint32_t maxValue = 1; bool allowFwdDeclare = false; @@ -620,7 +620,7 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { if (Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Node is a parameter but parent isn't a function", i); break; @@ -648,7 +648,7 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { break; default: - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Node is an if/scope/do/for/while/switch but parent isn't of a similar " "type or function", i); } @@ -679,7 +679,7 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { case D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE: case D3D12_HLSL_NODE_TYPE_PARAMETER: if (node.GetChildCount()) - return DXC_REFLECT_ERR("Node is a parameter, typedef, variable or " + return HLSL_REFL_ERR("Node is a parameter, typedef, variable or " "static variable but also has children", i); case D3D12_HLSL_NODE_TYPE_IF: @@ -696,185 +696,185 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { node.GetNodeType() == D3D12_HLSL_NODE_TYPE_VARIABLE) && Nodes[node.GetParentId()].GetNodeType() == D3D12_HLSL_NODE_TYPE_INTERFACE) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Node is interface but has registers or variables", i); if (node.IsFwdDeclare() && !allowFwdDeclare) - return DXC_REFLECT_ERR("Node is fwd declare but that's not permitted", i); + return HLSL_REFL_ERR("Node is fwd declare but that's not permitted", i); if (node.GetLocalId() >= maxValue) - return DXC_REFLECT_ERR("Node has invalid localId", i); + return HLSL_REFL_ERR("Node has invalid localId", i); } for(uint32_t i = 0; i < header.Registers; ++i) { - const DxcHLSLRegister ® = Registers[i]; + const ReflectionShaderResource ® = Registers[i]; if(reg.GetNodeId() >= header.Nodes || Nodes[reg.GetNodeId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER || Nodes[reg.GetNodeId()].GetLocalId() != i ) - return DXC_REFLECT_ERR("Register points to an invalid nodeId", i); + return HLSL_REFL_ERR("Register points to an invalid nodeId", i); if (reg.GetType() > D3D_SIT_UAV_FEEDBACKTEXTURE || reg.GetReturnType() > D3D_RETURN_TYPE_CONTINUED || reg.GetDimension() > D3D_SRV_DIMENSION_BUFFEREX || !reg.GetBindCount() || (reg.GetArrayId() != uint32_t(-1) && reg.GetArrayId() >= header.Arrays) || (reg.GetArrayId() != uint32_t(-1) && reg.GetBindCount() <= 1)) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Register invalid type, returnType, bindCount, array or dimension", i); D3D_CBUFFER_TYPE bufferType = - DxcHLSLReflectionData::GetBufferType(reg.GetType()); + ReflectionData::GetBufferType(reg.GetType()); if(bufferType != D3D_CT_INTERFACE_POINTERS) { if (reg.GetBufferId() >= header.Buffers || Buffers[reg.GetBufferId()].NodeId != reg.GetNodeId() || Buffers[reg.GetBufferId()].Type != bufferType) - return DXC_REFLECT_ERR("Register invalid buffer referenced by register", i); + return HLSL_REFL_ERR("Register invalid buffer referenced by register", i); } } for (uint32_t i = 0; i < header.Functions; ++i) { - const DxcHLSLFunction &func = Functions[i]; + const ReflectionFunction &func = Functions[i]; if (func.GetNodeId() >= header.Nodes || Nodes[func.GetNodeId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION || Nodes[func.GetNodeId()].GetLocalId() != i) - return DXC_REFLECT_ERR("Function points to an invalid nodeId", i); + return HLSL_REFL_ERR("Function points to an invalid nodeId", i); uint32_t paramCount = func.GetNumParameters() + func.HasReturn(); if (Nodes[func.GetNodeId()].GetChildCount() < paramCount) - return DXC_REFLECT_ERR("Function is missing parameters and/or return", i); + return HLSL_REFL_ERR("Function is missing parameters and/or return", i); for (uint32_t j = 0; j < paramCount; ++j) if (Nodes[func.GetNodeId() + 1 + j].GetParentId() != func.GetNodeId() || Nodes[func.GetNodeId() + 1 + j].GetNodeType() != D3D12_HLSL_NODE_TYPE_PARAMETER) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Function is missing valid parameters and/or return", i); } for(uint32_t i = 0; i < header.Enums; ++i) { - const DxcHLSLEnumDesc &enm = Enums[i]; + const ReflectionEnumeration &enm = Enums[i]; if (enm.NodeId >= header.Nodes || Nodes[enm.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM || Nodes[enm.NodeId].GetLocalId() != i) - return DXC_REFLECT_ERR("Function points to an invalid nodeId", i); + return HLSL_REFL_ERR("Function points to an invalid nodeId", i); if (enm.Type < D3D12_HLSL_ENUM_TYPE_START || enm.Type > D3D12_HLSL_ENUM_TYPE_END) - return DXC_REFLECT_ERR("Enum has an invalid type", i); + return HLSL_REFL_ERR("Enum has an invalid type", i); - const DxcHLSLNode &node = Nodes[enm.NodeId]; + const ReflectionNode &node = Nodes[enm.NodeId]; if (!node.IsFwdDeclare() && !node.GetChildCount()) - return DXC_REFLECT_ERR("Enum has no values!", i); + return HLSL_REFL_ERR("Enum has no values!", i); for (uint32_t j = 0; j < node.GetChildCount(); ++j) { - const DxcHLSLNode &child = Nodes[enm.NodeId + 1 + j]; + const ReflectionNode &child = Nodes[enm.NodeId + 1 + j]; if (child.GetChildCount() != 0 || child.GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM_VALUE) - return DXC_REFLECT_ERR("Enum has an invalid enum value", i); + return HLSL_REFL_ERR("Enum has an invalid enum value", i); } } for(uint32_t i = 0; i < header.EnumValues; ++i) { - const DxcHLSLEnumValue &enumVal = EnumValues[i]; + const ReflectionEnumValue &enumVal = EnumValues[i]; if (enumVal.NodeId >= header.Nodes || Nodes[enumVal.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM_VALUE || Nodes[enumVal.NodeId].GetLocalId() != i || Nodes[Nodes[enumVal.NodeId].GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM) - return DXC_REFLECT_ERR("Enum points to an invalid nodeId", i); + return HLSL_REFL_ERR("Enum points to an invalid nodeId", i); } for (uint32_t i = 0; i < header.Arrays; ++i) { - const DxcHLSLArray &arr = Arrays[i]; + const ReflectionArray &arr = Arrays[i]; if (arr.ArrayElem() <= 1 || arr.ArrayElem() > 32 || arr.ArrayStart() + arr.ArrayElem() > header.ArraySizes) - return DXC_REFLECT_ERR("Array points to an invalid array element", i); + return HLSL_REFL_ERR("Array points to an invalid array element", i); } for (uint32_t i = 0; i < header.Annotations; ++i) if (Annotations[i].GetStringNonDebug() >= header.StringsNonDebug) - return DXC_REFLECT_ERR("Annotation points to an invalid string", i); + return HLSL_REFL_ERR("Annotation points to an invalid string", i); for (uint32_t i = 0; i < header.Buffers; ++i) { - const DxcHLSLBuffer &buf = Buffers[i]; + const ReflectionShaderBuffer &buf = Buffers[i]; if (buf.NodeId >= header.Nodes || Nodes[buf.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER || Nodes[buf.NodeId].GetLocalId() >= header.Registers || Registers[Nodes[buf.NodeId].GetLocalId()].GetBufferId() != i) - return DXC_REFLECT_ERR("Buffer points to an invalid nodeId", i); + return HLSL_REFL_ERR("Buffer points to an invalid nodeId", i); - const DxcHLSLNode &node = Nodes[buf.NodeId]; + const ReflectionNode &node = Nodes[buf.NodeId]; if (!node.GetChildCount()) - return DXC_REFLECT_ERR("Buffer requires at least one Variable child", i); + return HLSL_REFL_ERR("Buffer requires at least one Variable child", i); for (uint32_t j = 0; j < node.GetChildCount(); ++j) { - const DxcHLSLNode &child = Nodes[buf.NodeId + 1 + j]; + const ReflectionNode &child = Nodes[buf.NodeId + 1 + j]; if (child.GetChildCount() != 0 || child.GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) - return DXC_REFLECT_ERR("Buffer has to have only Variable child nodes", i); + return HLSL_REFL_ERR("Buffer has to have only Variable child nodes", i); } } for (uint32_t i = 0; i < header.Members; ++i) { if (MemberTypeIds[i] >= header.Types) - return DXC_REFLECT_ERR("Member points to an invalid type", i); + return HLSL_REFL_ERR("Member points to an invalid type", i); if (hasSymbolInfo && MemberNameIds[i] >= header.Strings) - return DXC_REFLECT_ERR("Member points to an invalid string", i); + return HLSL_REFL_ERR("Member points to an invalid string", i); } for (uint32_t i = 0; i < header.TypeListCount; ++i) if (TypeList[i] >= header.Types) - return DXC_REFLECT_ERR("Type list index points to an invalid type", i); + return HLSL_REFL_ERR("Type list index points to an invalid type", i); for (uint32_t i = 0; i < header.Parameters; ++i) { - const DxcHLSLParameter ¶m = Parameters[i]; + const ReflectionFunctionParameter ¶m = Parameters[i]; if (param.NodeId >= header.Nodes || Nodes[param.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_PARAMETER || Nodes[param.NodeId].GetLocalId() != i || param.TypeId >= header.Types) - return DXC_REFLECT_ERR("Parameter points to an invalid nodeId", i); + return HLSL_REFL_ERR("Parameter points to an invalid nodeId", i); if (param.Flags > 3 || param.InterpolationMode > D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE) - return DXC_REFLECT_ERR("Parameter has invalid data", i); + return HLSL_REFL_ERR("Parameter has invalid data", i); } for (uint32_t nodeId : validateChildren) { - const DxcHLSLNode &node = Nodes[nodeId]; + const ReflectionNode &node = Nodes[nodeId]; // If/Then/Scope children could only be // struct/union/interface/if/variable/typedef/enum for (uint32_t j = 0; j < node.GetChildCount(); ++j) { - const DxcHLSLNode &childNode = Nodes[nodeId + 1 + j]; + const ReflectionNode &childNode = Nodes[nodeId + 1 + j]; switch (childNode.GetNodeType()) { case D3D12_HLSL_NODE_TYPE_VARIABLE: @@ -891,7 +891,7 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { case D3D12_HLSL_NODE_TYPE_SWITCH: break; default: - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Node has if/then/scope with children of invalid type", nodeId); } @@ -901,22 +901,22 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { for (uint32_t i = 0; i < header.Statements; ++i) { - const DxcHLSLStatement &Stmt = Statements[i]; + const ReflectionScopeStmt &Stmt = Statements[i]; if (Stmt.GetNodeId() >= header.Nodes || Nodes[Stmt.GetNodeId()].GetLocalId() != i) - return DXC_REFLECT_ERR("Statement points to an invalid nodeId", i); + return HLSL_REFL_ERR("Statement points to an invalid nodeId", i); bool condVar = Stmt.HasConditionVar(); uint32_t minParamCount = Stmt.GetNodeCount() + condVar; - const DxcHLSLNode &node = Nodes[Stmt.GetNodeId()]; + const ReflectionNode &node = Nodes[Stmt.GetNodeId()]; if (node.GetChildCount() < minParamCount) - return DXC_REFLECT_ERR("Statement didn't have required child nodes", i); + return HLSL_REFL_ERR("Statement didn't have required child nodes", i); if (condVar && Nodes[Stmt.GetNodeId() + 1].GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Statement has condition variable but first child is not a variable", i); switch (Nodes[Stmt.GetNodeId()].GetNodeType()) { @@ -926,23 +926,23 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { case D3D12_HLSL_NODE_TYPE_SWITCH: break; default: - return DXC_REFLECT_ERR("Statement has invalid node type", i); + return HLSL_REFL_ERR("Statement has invalid node type", i); } } for (uint32_t i = 0; i < header.Types; ++i) { - const DxcHLSLType &type = Types[i]; + const ReflectionVariableType &type = Types[i]; if (hasSymbolInfo && (TypeSymbols[i].DisplayNameId >= header.Strings || TypeSymbols[i].UnderlyingNameId >= header.Strings)) - return DXC_REFLECT_ERR("Type points to an invalid string", i); + return HLSL_REFL_ERR("Type points to an invalid string", i); if (hasSymbolInfo && (TypeSymbols[i].DisplayArray.ElementsOrArrayId >> 31 && (TypeSymbols[i].DisplayArray.ElementsOrArrayId << 1 >> 1) >= header.Arrays)) - return DXC_REFLECT_ERR("Type points to an invalid string", i); + return HLSL_REFL_ERR("Type points to an invalid string", i); if ((type.GetBaseClass() != uint32_t(-1) && type.GetBaseClass() >= header.Types) || @@ -952,7 +952,7 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { (type.GetUnderlyingArray().ElementsOrArrayId >> 31 && (type.GetUnderlyingArray().ElementsOrArrayId << 1 >> 1) >= header.Arrays)) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Type points to an invalid string, array, base class or member", i); switch (type.GetClass()) { @@ -960,14 +960,14 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { case D3D_SVC_SCALAR: if (type.GetColumns() != 1) - return DXC_REFLECT_ERR("Type (scalar) should have columns == 1", i); + return HLSL_REFL_ERR("Type (scalar) should have columns == 1", i); [[fallthrough]]; case D3D_SVC_VECTOR: if (type.GetRows() != 1) - return DXC_REFLECT_ERR("Type (scalar/vector) should have rows == 1", i); + return HLSL_REFL_ERR("Type (scalar/vector) should have rows == 1", i); [[fallthrough]]; @@ -976,7 +976,7 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { if (!type.GetRows() || !type.GetColumns() || type.GetRows() > 128 || type.GetColumns() > 128) - return DXC_REFLECT_ERR("Type (scalar/vector/matrix) has invalid rows or columns", i); + return HLSL_REFL_ERR("Type (scalar/vector/matrix) has invalid rows or columns", i); switch (type.GetType()) { case D3D_SVT_BOOL: @@ -998,7 +998,7 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { break; default: - return DXC_REFLECT_ERR("Type (scalar/matrix/vector) is of invalid type", i); + return HLSL_REFL_ERR("Type (scalar/matrix/vector) is of invalid type", i); } break; @@ -1006,17 +1006,17 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { case D3D_SVC_STRUCT: if (!type.GetMemberCount()) - return DXC_REFLECT_ERR("Type (struct) is missing children", i); + return HLSL_REFL_ERR("Type (struct) is missing children", i); [[fallthrough]]; case D3D_SVC_INTERFACE_CLASS: if (type.GetType()) - return DXC_REFLECT_ERR("Type (struct) shouldn't have rows or columns", i); + return HLSL_REFL_ERR("Type (struct) shouldn't have rows or columns", i); if (type.GetRows() || type.GetColumns()) - return DXC_REFLECT_ERR("Type (struct) shouldn't have rows or columns", i); + return HLSL_REFL_ERR("Type (struct) shouldn't have rows or columns", i); break; @@ -1053,16 +1053,16 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { break; default: - return DXC_REFLECT_ERR("Type (object) is of invalid type", i); + return HLSL_REFL_ERR("Type (object) is of invalid type", i); } if (type.GetRows() || type.GetColumns()) - return DXC_REFLECT_ERR("Type (object) shouldn't have rows or columns", i); + return HLSL_REFL_ERR("Type (object) shouldn't have rows or columns", i); break; default: - return DXC_REFLECT_ERR("Type has an invalid class", i); + return HLSL_REFL_ERR("Type has an invalid class", i); } } @@ -1070,40 +1070,40 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { for (uint32_t i = 0; i < header.Nodes; ++i) { - const DxcHLSLNode &node = Nodes[i]; + const ReflectionNode &node = Nodes[i]; if (node.IsFwdBckDefined()) { uint32_t fwdBack = node.GetFwdBck(); if (Nodes[fwdBack].GetNodeType() != node.GetNodeType()) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Node (fwd/bck declare) points to element that of incompatible type", i); if (hasSymbolInfo && NodeSymbols[fwdBack].GetNameId() != NodeSymbols[i].GetNameId()) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Node (fwd/bck declare) have mismatching name", i); if (node.IsFwdDeclare()) { if (fwdBack <= i || fwdBack >= header.Nodes) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Node (fwd declare) points to invalid element", i); if (Nodes[fwdBack].IsFwdDeclare()) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Node (fwd declare) points to element that is also a fwd declare", i); uint32_t paramCount = 0; if (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_FUNCTION) { - const DxcHLSLFunction &func = Functions[node.GetLocalId()]; + const ReflectionFunction &func = Functions[node.GetLocalId()]; paramCount = func.GetNumParameters() + func.HasReturn(); } if ((node.GetChildCount() != paramCount) || node.GetAnnotationCount()) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Node (fwd declare) points to element with invalid child count, " "or annotationCount", i); } @@ -1111,11 +1111,11 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { else { if (fwdBack >= i) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Node (bck declare) points to invalid element", i); if (!Nodes[fwdBack].IsFwdDeclare()) - return DXC_REFLECT_ERR( + return HLSL_REFL_ERR( "Node (bck declare) points to element that is not a fwd declare", i); } } @@ -1126,7 +1126,7 @@ D3D_CBUFFER_TYPE DxcHLSLReflectionData::GetBufferType(uint8_t Type) { if (MakeNameLookupTable) GenerateNameLookupTable(); - return DxcReflectionSuccess; + return ReflectionErrorSuccess; } } // namespace hlsl diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 0837dbf5da..e433f76d38 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -349,8 +349,8 @@ static std::string BufferTypeToString(D3D_CBUFFER_TYPE Type) { return arr[Type]; } -static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, - const DxcHLSLType &Type) { +static std::string GetBuiltinTypeName(const ReflectionData &Refl, + const ReflectionVariableType &Type) { std::string type = ""; @@ -447,8 +447,8 @@ static std::string GetBuiltinTypeName(const DxcHLSLReflectionData &Refl, return type; } -static void FillArraySizes(const DxcHLSLReflectionData &Reflection, - DxcHLSLArrayOrElements Elements, +static void FillArraySizes(const ReflectionData &Reflection, + ReflectionArrayOrElements Elements, std::vector &Array) { if (!Elements.IsArray()) @@ -459,7 +459,7 @@ static void FillArraySizes(const DxcHLSLReflectionData &Reflection, return; } - const DxcHLSLArray &arr = + const ReflectionArray &arr = Reflection.Arrays[Elements.GetMultiDimensionalArrayId()]; for (uint32_t i = 0; i < arr.ArrayElem(); ++i) @@ -467,8 +467,8 @@ static void FillArraySizes(const DxcHLSLReflectionData &Reflection, } static void PrintSymbol(JsonWriter &Json, - const DxcHLSLReflectionData &Reflection, - const DxcHLSLNodeSymbol &Sym, bool IsVerbose, + const ReflectionData &Reflection, + const ReflectionNodeSymbol &Sym, bool IsVerbose, bool AllRelevantMembers, bool MuteName = false) { if ((Sym.GetNameId() || IsVerbose) && !MuteName) { @@ -512,10 +512,10 @@ static void PrintSymbol(JsonWriter &Json, //Verbose and all members are slightly different; //Verbose will still print fields even if they aren't relevant, // while all members will not silence important info but that might not matter for human readability -static void PrintNode(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, +static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, uint32_t NodeId, bool IsVerbose, bool AllRelevantMembers) { - const DxcHLSLNode &node = Reflection.Nodes[NodeId]; + const ReflectionNode &node = Reflection.Nodes[NodeId]; bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -556,7 +556,7 @@ static void PrintNode(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, Json.Array("Annotations", [&Reflection, &Json, node] { for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) { - const DxcHLSLAnnotation &annot = + const ReflectionAnnotation &annot = Reflection.Annotations[node.GetAnnotationStart() + i]; std::string name = @@ -585,7 +585,7 @@ static void PrintNode(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, Json.Object("Symbol", [&Reflection, &Json, NodeId, IsVerbose, AllRelevantMembers] { - const DxcHLSLNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; + const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers); }); @@ -593,11 +593,11 @@ static void PrintNode(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, Json.NullField("Symbol"); } -static void PrintRegister(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, +static void PrintRegister(JsonWriter &Json, const ReflectionData &Reflection, uint32_t RegisterId, bool IsVerbose, bool AllRelevantMembers) { - const DxcHLSLRegister ® = Reflection.Registers[RegisterId]; + const ReflectionShaderResource ® = Reflection.Registers[RegisterId]; bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -640,7 +640,7 @@ static void PrintRegister(JsonWriter &Json, const DxcHLSLReflectionData &Reflect if (reg.GetArrayId() == uint32_t(-1)) return; - const DxcHLSLArray &arr = Reflection.Arrays[reg.GetArrayId()]; + const ReflectionArray &arr = Reflection.Arrays[reg.GetArrayId()]; for (uint32_t i = 0; i < uint32_t(arr.ArrayElem()); ++i) Json.Value(uint64_t(Reflection.ArraySizes[arr.ArrayStart() + i])); @@ -686,7 +686,7 @@ static void PrintRegister(JsonWriter &Json, const DxcHLSLReflectionData &Reflect } } -static void PrintTypeName(const DxcHLSLReflectionData &Reflection, uint32_t TypeId, +static void PrintTypeName(const ReflectionData &Reflection, uint32_t TypeId, bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, JsonWriter &Json, const char *NameForTypeName = "Name") { @@ -700,7 +700,7 @@ static void PrintTypeName(const DxcHLSLReflectionData &Reflection, uint32_t Type std::string underlyingName; std::vector underlyingArraySizes; - const DxcHLSLType &type = Reflection.Types[TypeId]; + const ReflectionVariableType &type = Reflection.Types[TypeId]; if (!HasSymbols) { name = GetBuiltinTypeName(Reflection, type); @@ -708,7 +708,7 @@ static void PrintTypeName(const DxcHLSLReflectionData &Reflection, uint32_t Type } else { - const DxcHLSLTypeSymbol &symbol = Reflection.TypeSymbols[TypeId]; + const ReflectionVariableTypeSymbol &symbol = Reflection.TypeSymbols[TypeId]; name = Reflection.Strings[symbol.DisplayNameId]; FillArraySizes(Reflection, symbol.DisplayArray, arraySizes); underlyingName = Reflection.Strings[symbol.UnderlyingNameId]; @@ -734,12 +734,12 @@ static void PrintTypeName(const DxcHLSLReflectionData &Reflection, uint32_t Type }); } -static void PrintType(const DxcHLSLReflectionData &Reflection, uint32_t TypeId, +static void PrintType(const ReflectionData &Reflection, uint32_t TypeId, bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, JsonWriter &Json, bool Recursive, const char *NameForTypeName = "Name") { - const DxcHLSLType &type = Reflection.Types[TypeId]; + const ReflectionVariableType &type = Reflection.Types[TypeId]; PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, Json, NameForTypeName); @@ -802,7 +802,7 @@ static void PrintType(const DxcHLSLReflectionData &Reflection, uint32_t TypeId, Json.NullField("Members"); } -static void PrintParameter(const DxcHLSLReflectionData &Reflection, uint32_t TypeId, +static void PrintParameter(const ReflectionData &Reflection, uint32_t TypeId, bool HasSymbols, bool IsVerbose, JsonWriter &Json, uint32_t SemanticId, uint8_t InterpolationMode, uint8_t Flags, bool AllRelevantMembers) { @@ -843,11 +843,11 @@ static void PrintParameter(const DxcHLSLReflectionData &Reflection, uint32_t Typ Json.StringField("Interpolation", interpolationModes[InterpolationMode]); } -static void PrintFunction(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, +static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, uint32_t FunctionId, bool IsVerbose, bool AllRelevantMembers) { - const DxcHLSLFunction &func = Reflection.Functions[FunctionId]; + const ReflectionFunction &func = Reflection.Functions[FunctionId]; bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -880,10 +880,10 @@ static void PrintFunction(JsonWriter &Json, const DxcHLSLReflectionData &Reflect for (uint32_t i = 0; i < uint32_t(func.GetNumParameters()); ++i) { uint32_t nodeId = func.GetNodeId() + 1 + i; - const DxcHLSLNode &node = Reflection.Nodes[nodeId]; + const ReflectionNode &node = Reflection.Nodes[nodeId]; uint32_t localId = node.GetLocalId(); - const DxcHLSLParameter ¶m = Reflection.Parameters[localId]; + const ReflectionFunctionParameter ¶m = Reflection.Parameters[localId]; std::string paramName = hasSymbols ? Reflection.Strings[Reflection.NodeSymbols[nodeId].GetNameId()] @@ -895,7 +895,7 @@ static void PrintFunction(JsonWriter &Json, const DxcHLSLReflectionData &Reflect if (hasSymbols) { - const DxcHLSLNodeSymbol &sym = Reflection.NodeSymbols[nodeId]; + const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[nodeId]; Json.Object("Symbol", [&Json, &Reflection, &sym, IsVerbose, AllRelevantMembers]() { @@ -929,9 +929,9 @@ static void PrintFunction(JsonWriter &Json, const DxcHLSLReflectionData &Reflect else { - const DxcHLSLNode &node = + const ReflectionNode &node = Reflection.Nodes[func.GetNodeId() + 1 + func.GetNumParameters()]; - const DxcHLSLParameter ¶m = Reflection.Parameters[node.GetLocalId()]; + const ReflectionFunctionParameter ¶m = Reflection.Parameters[node.GetLocalId()]; Json.Object("ReturnType", [&Reflection, &func, &Json, hasSymbols, IsVerbose, ¶m, &node, AllRelevantMembers]() { @@ -942,16 +942,16 @@ static void PrintFunction(JsonWriter &Json, const DxcHLSLReflectionData &Reflect } } -static void PrintEnumValue(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, +static void PrintEnumValue(JsonWriter &Json, const ReflectionData &Reflection, uint32_t NodeId, bool IsVerbose, bool AllRelevantMembers) { - const DxcHLSLNode &child = Reflection.Nodes[NodeId]; + const ReflectionNode &child = Reflection.Nodes[NodeId]; - const DxcHLSLEnumValue &val = Reflection.EnumValues[child.GetLocalId()]; + const ReflectionEnumValue &val = Reflection.EnumValues[child.GetLocalId()]; - const DxcHLSLNode &parent = Reflection.Nodes[child.GetParentId()]; - const DxcHLSLEnumDesc &enm = Reflection.Enums[parent.GetLocalId()]; + const ReflectionNode &parent = Reflection.Nodes[child.GetParentId()]; + const ReflectionEnumeration &enm = Reflection.Enums[parent.GetLocalId()]; switch (enm.Type) { case D3D12_HLSL_ENUM_TYPE_INT: @@ -969,7 +969,7 @@ static void PrintEnumValue(JsonWriter &Json, const DxcHLSLReflectionData &Reflec if (hasSymbols) { - const DxcHLSLNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; + const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; Json.Object( "Symbol", [&Json, &Reflection, &sym, IsVerbose, AllRelevantMembers]() { @@ -981,12 +981,12 @@ static void PrintEnumValue(JsonWriter &Json, const DxcHLSLReflectionData &Reflec Json.NullField("Symbol"); } -static void PrintEnum(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, +static void PrintEnum(JsonWriter &Json, const ReflectionData &Reflection, uint32_t EnumId, bool IsVerbose, bool AllRelevantMembers) { - const DxcHLSLEnumDesc &enm = Reflection.Enums[EnumId]; - const DxcHLSLNode &node = Reflection.Nodes[enm.NodeId]; + const ReflectionEnumeration &enm = Reflection.Enums[EnumId]; + const ReflectionNode &node = Reflection.Nodes[enm.NodeId]; bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -1022,19 +1022,19 @@ static void PrintEnum(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, }); } -static void PrintAnnotation(JsonWriter &Json, const DxcHLSLReflectionData &Reflection, - const DxcHLSLAnnotation &Annot) { +static void PrintAnnotation(JsonWriter &Json, const ReflectionData &Reflection, + const ReflectionAnnotation &Annot) { Json.StringField("Contents", Reflection.StringsNonDebug[Annot.GetStringNonDebug()]); Json.StringField("Type", Annot.GetIsBuiltin() ? "Builtin" : "User"); } -static uint32_t PrintBufferMember(const DxcHLSLReflectionData &Reflection, +static uint32_t PrintBufferMember(const ReflectionData &Reflection, uint32_t NodeId, uint32_t ChildId, bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, JsonWriter &Json) { - const DxcHLSLNode &node = Reflection.Nodes[NodeId]; + const ReflectionNode &node = Reflection.Nodes[NodeId]; JsonWriter::ObjectScope root(Json); @@ -1057,13 +1057,13 @@ static uint32_t PrintBufferMember(const DxcHLSLReflectionData &Reflection, return node.GetChildCount(); } -static void PrintBuffer(const DxcHLSLReflectionData &Reflection, uint32_t BufferId, +static void PrintBuffer(const ReflectionData &Reflection, uint32_t BufferId, bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, JsonWriter &Json) { JsonWriter::ObjectScope nodeRoot(Json); - const DxcHLSLBuffer &buf = Reflection.Buffers[BufferId]; - const DxcHLSLNode &node = Reflection.Nodes[buf.NodeId]; + const ReflectionShaderBuffer &buf = Reflection.Buffers[BufferId]; + const ReflectionNode &node = Reflection.Nodes[buf.NodeId]; bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -1092,11 +1092,11 @@ static void PrintBuffer(const DxcHLSLReflectionData &Reflection, uint32_t Buffer }); } -static void PrintStatement(const DxcHLSLReflectionData &Reflection, - const DxcHLSLStatement &Stmt, JsonWriter &Json, +static void PrintStatement(const ReflectionData &Reflection, + const ReflectionScopeStmt &Stmt, JsonWriter &Json, bool IsVerbose) { - const DxcHLSLNode &node = Reflection.Nodes[Stmt.GetNodeId()]; + const ReflectionNode &node = Reflection.Nodes[Stmt.GetNodeId()]; uint32_t nodesA = Stmt.GetNodeCount(); uint32_t nodesB = node.GetChildCount() - nodesA - Stmt.HasConditionVar(); @@ -1115,7 +1115,7 @@ static void PrintStatement(const DxcHLSLReflectionData &Reflection, Json.UIntField("NodesB", nodesB); } -uint32_t PrintNodeRecursive(const DxcHLSLReflectionData &Reflection, +uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, JsonWriter &Json, bool IsVerbose, bool IsHumanFriendly) { @@ -1125,7 +1125,7 @@ uint32_t PrintNodeRecursive(const DxcHLSLReflectionData &Reflection, //Self - DxcHLSLNode node = Reflection.Nodes[NodeId]; + ReflectionNode node = Reflection.Nodes[NodeId]; // If this happens, we found the one defining a fwd declare. // But this can happen in a different scope than the symbol ends up in. @@ -1149,7 +1149,7 @@ uint32_t PrintNodeRecursive(const DxcHLSLReflectionData &Reflection, if (nodeType == D3D12_HLSL_NODE_TYPE_FUNCTION) Json.Object("Function", [&node, &Reflection, &Json, IsVerbose, IsHumanFriendly, &childrenToSkip]() { - DxcHLSLFunction func = Reflection.Functions[node.GetLocalId()]; + ReflectionFunction func = Reflection.Functions[node.GetLocalId()]; PrintFunction(Json, Reflection, node.GetLocalId(), IsVerbose, !IsHumanFriendly); childrenToSkip = func.GetNumParameters() + func.HasReturn(); @@ -1256,7 +1256,7 @@ uint32_t PrintNodeRecursive(const DxcHLSLReflectionData &Reflection, Json.Object(stmtType, [&node, &Reflection, &Json, IsVerbose, IsHumanFriendly, NodeId, &childrenToSkip, nodeType]() { - const DxcHLSLStatement &stmt = Reflection.Statements[node.GetLocalId()]; + const ReflectionScopeStmt &stmt = Reflection.Statements[node.GetLocalId()]; uint32_t start = NodeId + 1; @@ -1339,7 +1339,7 @@ uint32_t PrintNodeRecursive(const DxcHLSLReflectionData &Reflection, //IsHumanFriendly = false: Raw view of the real file data //IsHumanFriendly = true: Clean view that's relatively close to the real tree -std::string DxcHLSLReflectionData::ToJson( +std::string ReflectionData::ToJson( bool IsHumanFriendly, bool IsVerbose) const { JsonWriter json; @@ -1407,7 +1407,7 @@ std::string DxcHLSLReflectionData::ToJson( for (uint32_t i = 0; i < uint32_t(Parameters.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - const DxcHLSLParameter ¶m = Parameters[i]; + const ReflectionFunctionParameter ¶m = Parameters[i]; std::string paramName = hasSymbols ? Strings[NodeSymbols[param.NodeId].GetNameId()] : std::to_string(i); @@ -1437,7 +1437,7 @@ std::string DxcHLSLReflectionData::ToJson( json.Array("Annotations", [this, &json, hasSymbols] { for (uint32_t i = 0; i < uint32_t(Annotations.size()); ++i) { - const DxcHLSLAnnotation &annot = Annotations[i]; + const ReflectionAnnotation &annot = Annotations[i]; JsonWriter::ObjectScope valueRoot(json); json.UIntField("StringId", annot.GetStringNonDebug()); PrintAnnotation(json, *this, annot); @@ -1446,7 +1446,7 @@ std::string DxcHLSLReflectionData::ToJson( json.Array("Arrays", [this, &json] { for (uint32_t i = 0; i < uint32_t(Arrays.size()); ++i) { - const DxcHLSLArray &arr = Arrays[i]; + const ReflectionArray &arr = Arrays[i]; JsonWriter::ObjectScope valueRoot(json); json.UIntField("ArrayElem", arr.ArrayElem()); json.UIntField("ArrayStart", arr.ArrayStart()); @@ -1500,7 +1500,7 @@ std::string DxcHLSLReflectionData::ToJson( json.Array("Statements", [this, &json, IsVerbose] { for (uint32_t i = 0; i < uint32_t(Statements.size()); ++i) { - const DxcHLSLStatement &stat = Statements[i]; + const ReflectionScopeStmt &stat = Statements[i]; JsonWriter::ObjectScope valueRoot(json); json.StringField( "Type", NodeTypeToString( From 594fda96d295816bdc95a63ae87a52a88b5b6d7e Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 9 Nov 2025 17:38:07 +0100 Subject: [PATCH 087/126] Some formatting --- .../dxcreflection/dxcreflection_from_ast.cpp | 28 +++++++++-------- .../DxcReflectionJson.cpp | 30 +++++++++---------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index e0c8fed929..7092d0ce40 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -97,6 +97,8 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, ++annotationCount; } + + // TODO: Other types of attrs } if (const ValueDecl *valDecl = dyn_cast(DeclSelf)) { @@ -116,6 +118,7 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, return err; semanticId = uint16_t(semanticId32); + break; } } } @@ -190,14 +193,14 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, if (start.isValid() && end.isValid()) { - PresumedLoc presumed = SM.getPresumedLoc(start); + PresumedLoc presumed = SM.getPresumedLoc(start); - SourceLocation realEnd = SM.getFileLoc(end); - SourceLocation endOfToken = - Lexer::getLocForEndOfToken(realEnd, 0, SM, LangOpts); - PresumedLoc presumedEnd = SM.getPresumedLoc(endOfToken); + SourceLocation realEnd = SM.getFileLoc(end); + SourceLocation endOfToken = + Lexer::getLocForEndOfToken(realEnd, 0, SM, LangOpts); + PresumedLoc presumedEnd = SM.getPresumedLoc(endOfToken); - if (presumed.isValid() && presumedEnd.isValid()) { + if (presumed.isValid() && presumedEnd.isValid()) { uint32_t startLine = presumed.getLine(); uint32_t startCol = presumed.getColumn(); @@ -249,20 +252,21 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, sourceColumnStart = startCol; sourceColumnEnd = endCol; sourceId = uint16_t(i); - } + } } uint32_t nameId; if (ReflectionError err = Refl.RegisterString(nameId, UnqualifiedName, false)) - return err; + return err; Refl.NodeSymbols.push_back({}); - if(ReflectionError err = ReflectionNodeSymbol::Initialize(Refl.NodeSymbols.back(), nameId, sourceId, sourceLineCount, sourceLineStart, - sourceColumnStart, sourceColumnEnd)) - return err; + if (ReflectionError err = ReflectionNodeSymbol::Initialize( + Refl.NodeSymbols.back(), nameId, sourceId, sourceLineCount, + sourceLineStart, sourceColumnStart, sourceColumnEnd)) + return err; } // Link @@ -1047,8 +1051,6 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId, bool DefaultRowMaj) { - ArrayRef UA = ValDesc->getUnusualAnnotations(); - DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); uint32_t nodeId; diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index e433f76d38..23926cb1e5 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -509,9 +509,9 @@ static void PrintSymbol(JsonWriter &Json, } } -//Verbose and all members are slightly different; -//Verbose will still print fields even if they aren't relevant, -// while all members will not silence important info but that might not matter for human readability +// Verbose and all members are slightly different; +// Verbose will still print fields even if they aren't relevant, +// while all members will not silence important info but that might not matter for human readability static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, uint32_t NodeId, bool IsVerbose, bool AllRelevantMembers) { @@ -1123,7 +1123,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - //Self + // Self ReflectionNode node = Reflection.Nodes[NodeId]; @@ -1144,7 +1144,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t childrenToSkip = 0; - //Function + // Function if (nodeType == D3D12_HLSL_NODE_TYPE_FUNCTION) Json.Object("Function", [&node, &Reflection, &Json, IsVerbose, @@ -1158,7 +1158,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, else if (IsVerbose) Json.NullField("Function"); - //Register + // Register if (nodeType == D3D12_HLSL_NODE_TYPE_REGISTER) Json.Object("Register", @@ -1170,7 +1170,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, else if (IsVerbose) Json.NullField("Register"); - //Enum + // Enum if (nodeType == D3D12_HLSL_NODE_TYPE_ENUM) Json.Object("Enum", [&node, &Reflection, &Json, IsVerbose, IsHumanFriendly, @@ -1183,7 +1183,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, else if (IsVerbose) Json.NullField("Enum"); - //Type + // Type bool isType = false; bool recurseType = false; @@ -1211,10 +1211,10 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, else if (IsVerbose) Json.NullField("Type"); - //If; turns into ("Condition"), ("Body"), ("Else") - //While; turns into ("Condition"), ("Body") - //For; turns into ("Condition"), ("Init"), ("Body") - //Switch; turns into ("Condition"), ("Body") + // If; turns into ("Condition"), ("Body"), ("Else") + // While; turns into ("Condition"), ("Body") + // For; turns into ("Condition"), ("Init"), ("Body") + // Switch; turns into ("Condition"), ("Body") const char *stmtType = nullptr; @@ -1320,7 +1320,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, Json.NullField("For"); } - //Children + // Children uint32_t start = NodeId + 1 + childrenToSkip; uint32_t end = NodeId + 1 + node.GetChildCount(); @@ -1337,8 +1337,8 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, return node.GetChildCount(); } -//IsHumanFriendly = false: Raw view of the real file data -//IsHumanFriendly = true: Clean view that's relatively close to the real tree +// IsHumanFriendly = false: Raw view of the real file data +// IsHumanFriendly = true: Clean view that's relatively close to the real tree std::string ReflectionData::ToJson( bool IsHumanFriendly, bool IsVerbose) const { From f209f66e93fbcd45f87d99a681c741505216af3e Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 9 Nov 2025 17:58:19 +0100 Subject: [PATCH 088/126] Looked through the final files for a review and put the debug deserialization/serialization test in a debug only mode. Also fixed proper error messages there. --- .../tools/dxcreflection/dxcreflector.cpp | 64 ++++++++++--------- .../DxcReflectionContainer.cpp | 17 +++-- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 9b31bef27a..6033c4f3ae 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -1601,54 +1601,58 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, if (ReflectionError err = DxcHLSLReflectionDataFromAST( refl, astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, reflectMask, opts.DefaultRowMajor)) { - printf("DxcHLSLReflectionDataFromAST failed %s\n", err.err); //TODO: + fprintf(stderr, "DxcHLSLReflectionDataFromAST failed %s\n", err.err); return E_FAIL; } printf("%s\n", refl.ToJson().c_str()); - // Test serialization + // Debug: Verify deserialization, otherwise print error. - std::vector bytes; - refl.Dump(bytes); + #ifndef NDEBUG - ReflectionData deserialized; - - if (ReflectionError err = deserialized.Deserialize(bytes, true)) { - printf("Deserialize failed %s\n", err.err); // TODO: - return E_FAIL; - } + std::vector bytes; + refl.Dump(bytes); - if (!(deserialized == refl)) { - printf("Dump or Deserialize doesn't match\n"); //TODO: - return E_FAIL; - } + ReflectionData deserialized; - printf("Reflection size: %" PRIu64 "\n", bytes.size()); + if (ReflectionError err = deserialized.Deserialize(bytes, true)) { + fprintf(stderr, "Deserialize failed %s\n", err.err); + return E_FAIL; + } - // Test stripping symbols + if (!(deserialized == refl)) { + fprintf(stderr, "Dump or Deserialize doesn't match\n"); + return E_FAIL; + } - refl.StripSymbols(); + printf("Reflection binary size: %" PRIu64 "\n", bytes.size()); - printf("%s\n", refl.ToJson().c_str()); + // Test stripping symbols - refl.Dump(bytes); + if (!opts.ReflOpt.DisableSymbols) { - ReflectionData deserialized2; + deserialized.StripSymbols(); + deserialized.Dump(bytes); - if (ReflectionError err = deserialized2.Deserialize(bytes, true)) { - printf("Deserialize failed %s\n", err.err); // TODO: - return E_FAIL; - } + ReflectionData deserialized2; - if (!(deserialized2 == refl)) { - printf("Dump or Deserialize doesn't match\n"); //TODO: - return E_FAIL; - } + if (ReflectionError err = deserialized2.Deserialize(bytes, true)) { + fprintf(stderr, "Deserialize failed %s\n", err.err); + return E_FAIL; + } + + if (!(deserialized2 == deserialized)) { + fprintf(stderr, "Dump or Deserialize doesn't match\n"); + return E_FAIL; + } + + printf("Stripped reflection size: %" PRIu64 "\n", bytes.size()); + } - printf("Stripped reflection size: %" PRIu64 "\n", bytes.size()); + #endif - reflection = std::move(deserialized); + reflection = std::move(refl); // Flush and return results. o.flush(); diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index 2daee0631b..b47e41671c 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -16,10 +16,9 @@ namespace hlsl { -[[nodiscard]] ReflectionError ReflectionData::RegisterString( - uint32_t &StringId, - const std::string &Name, - bool IsNonDebug) { +[[nodiscard]] ReflectionError +ReflectionData::RegisterString(uint32_t &StringId, const std::string &Name, + bool IsNonDebug) { if (Name.size() >= 32768) return HLSL_REFL_ERR("Strings are limited to 32767"); @@ -369,8 +368,8 @@ template return ReflectionErrorSuccess; } -static constexpr uint32_t DxcReflectionDataMagic = DXC_FOURCC('D', 'H', 'R', 'D'); -static constexpr uint16_t DxcReflectionDataVersion = 0; +static constexpr uint32_t ReflectionDataMagic = DXC_FOURCC('H', 'L', 'R', 'D'); +static constexpr uint16_t ReflectionDataVersion = 0; void ReflectionData::StripSymbols() { Strings.clear(); @@ -480,7 +479,7 @@ void ReflectionData::Dump(std::vector &Bytes) const { toReserve = 0; UnsafeCast(Bytes, toReserve) = { - DxcReflectionDataMagic, DxcReflectionDataVersion, + ReflectionDataMagic, ReflectionDataVersion, uint16_t(Sources.size()), Features, uint32_t(StringsNonDebug.size()), uint32_t(Strings.size()), uint32_t(Nodes.size()), uint32_t(Registers.size()), @@ -532,10 +531,10 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { if (ReflectionError err = Consume(Bytes, off, header)) return err; - if (header.MagicNumber != DxcReflectionDataMagic) + if (header.MagicNumber != ReflectionDataMagic) return HLSL_REFL_ERR("Invalid magic number"); - if (header.Version != DxcReflectionDataVersion) + if (header.Version != ReflectionDataVersion) return HLSL_REFL_ERR("Unrecognized version number"); Features = header.Features; From 79c9e1be2a784b6b02a970602322af4a53df7446 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 9 Nov 2025 21:54:30 +0100 Subject: [PATCH 089/126] Fixed passing invalid encoded arguments to reflector api in dxreflector.cpp --- tools/clang/tools/dxreflector/dxreflector.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tools/clang/tools/dxreflector/dxreflector.cpp b/tools/clang/tools/dxreflector/dxreflector.cpp index 5825d65a07..5055d1ad5f 100644 --- a/tools/clang/tools/dxreflector/dxreflector.cpp +++ b/tools/clang/tools/dxreflector/dxreflector.cpp @@ -173,11 +173,20 @@ int main(int argc, const char **argv) { IFT(pLibrary->CreateIncludeHandler(&pIncludeHandler)); IFT(dxcSupport.CreateInstance(CLSID_DxcReflector, &pReflector)); - IFT(pReflector->FromSource(pSource, wName.c_str(), - (LPCWSTR*)argStrings.Utf8CharPtrVector.data(), - uint32_t(argStrings.Utf8CharPtrVector.size()), - nullptr, 0, pIncludeHandler, - &pRewriteResult)); + std::vector wargs; + std::vector wargsC; + + wargs.reserve(argStrings.Utf8CharPtrVector.size()); + wargsC.reserve(argStrings.Utf8CharPtrVector.size()); + + for (const std::string &arg : argStrings.Utf8CharPtrVector) { + wargs.push_back(std::wstring(CA2W(arg.c_str()))); + wargsC.push_back(wargs.back().c_str()); + } + + IFT(pReflector->FromSource(pSource, wName.c_str(), wargsC.data(), + uint32_t(wargsC.size()), nullptr, 0, + pIncludeHandler, &pRewriteResult)); if (dxreflectorOpts.OutputObject.empty()) { // No -Fo, print to console From 89f855dcb0974c29ea9a11da94a17abc1fd22262 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 9 Nov 2025 23:17:33 +0100 Subject: [PATCH 090/126] Added unwrapping of enum types to get underlying uint/int type --- .../tools/dxcreflection/dxcreflection_from_ast.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 7092d0ce40..10162a944b 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -550,6 +550,20 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, display = arr->getElementType().getNonReferenceType(); } + // Unwrap enum in underlying to still treat it as a uint/int/etc. + + if (const EnumType *enumTy = dyn_cast(underlying)) { + + const EnumDecl *decl = enumTy->getDecl(); + + if (decl && !decl->getIntegerType().isNull()) + underlying = + decl->getIntegerType().getNonReferenceType().getCanonicalType(); + + else + underlying = ASTCtx.IntTy; + } + // Name; Omit struct, class and const keywords PrintingPolicy policy(ASTCtx.getLangOpts()); From 0a83b6c4fcc926b4631d6641cdc7ad50809f8dd5 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 10 Nov 2025 00:35:27 +0100 Subject: [PATCH 091/126] Fixed problems with typedefs of resources and default template arguments for builtin types --- .../dxcreflection/dxcreflection_from_ast.cpp | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 10162a944b..e53dc537b7 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -741,11 +741,43 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, const TemplateSpecializationType *templateDesc = display->getAs(); - assert(templateDesc && "Expected a valid TemplateSpecializationType"); - innerType = templateDesc->getArg(0).getAsType(); + // Case 1: T = StructuredBuffer then underlying has a type, but sugared doesn't. + // Loses syntax sugar, but will still be correct. - if (svt == D3D_SVT_RWBUFFER || svt == D3D_SVT_BUFFER || svt == D3D_SVT_CBUFFER) - innerTypeName = innerType.getUnqualifiedType().getAsString(policy); + bool useUnderlying = !templateDesc; + + // Case 2: TextureCube = TextureCube + + if (templateDesc && displayName == underlyingName && + !templateDesc->getNumArgs()) + useUnderlying = true; + + if (useUnderlying) { + + assert(params.size() && + "Expected a TemplateSpecializationType with > 0 args"); + + innerType = params[0].getAsType(); + + if (svt == D3D_SVT_RWBUFFER || svt == D3D_SVT_BUFFER || + svt == D3D_SVT_CBUFFER) + innerTypeName = + innerType.getUnqualifiedType().getAsString(policy); + + } else { + + assert(templateDesc && + "Expected a valid TemplateSpecializationType"); + assert(templateDesc->getNumArgs() && + "Expected a TemplateSpecializationType with > 0 args"); + + innerType = templateDesc->getArg(0).getAsType(); + + if (svt == D3D_SVT_RWBUFFER || svt == D3D_SVT_BUFFER || + svt == D3D_SVT_CBUFFER) + innerTypeName = + innerType.getUnqualifiedType().getAsString(policy); + } } } } From cdeb6b02a75574d9d1c6462bf04ff5a28bfbcad7 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 10 Nov 2025 18:07:39 +0100 Subject: [PATCH 092/126] Disabled printing buffer id when BAB is encountered --- .../tools/dxcreflectioncontainer/DxcReflectionJson.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 23926cb1e5..2c86625855 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -647,7 +647,7 @@ static void PrintRegister(JsonWriter &Json, const ReflectionData &Reflection, }); } - bool isBuffer = true; + bool printBufferId = true; switch (reg.GetType()) { case D3D_SIT_TEXTURE: @@ -655,11 +655,13 @@ static void PrintRegister(JsonWriter &Json, const ReflectionData &Reflection, case D3D_SIT_UAV_RWTYPED: case D3D_SIT_RTACCELERATIONSTRUCTURE: case D3D_SIT_UAV_FEEDBACKTEXTURE: - isBuffer = false; + case D3D_SIT_UAV_RWBYTEADDRESS: + case D3D_SIT_BYTEADDRESS: + printBufferId = false; break; } - if (isBuffer || IsVerbose) + if (printBufferId || IsVerbose) Json.UIntField("BufferId", reg.GetBufferId()); if (reg.GetFlags() || IsVerbose) { From e451f4685e93507d746196eb722aec3bd8ffa1c2 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 10 Nov 2025 20:29:28 +0100 Subject: [PATCH 093/126] Now skipping forward declare information in human readable version. Backward declares are now skipped from being shown in the human friendly view. Fixed issue where forward declares would skip the wrong amount of children, breaking visualization of the AST. Fixed cmake issue --- .../dxcreflectioncontainer/CMakeLists.txt | 2 +- .../DxcReflectionJson.cpp | 42 ++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/tools/clang/tools/dxcreflectioncontainer/CMakeLists.txt b/tools/clang/tools/dxcreflectioncontainer/CMakeLists.txt index af848d992b..015d691afa 100644 --- a/tools/clang/tools/dxcreflectioncontainer/CMakeLists.txt +++ b/tools/clang/tools/dxcreflectioncontainer/CMakeLists.txt @@ -1,4 +1,4 @@ # Copyright (C) Microsoft Corporation. All rights reserved. # This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. -add_clang_library(dxcreflectioncontainer STATIC DxcReflection.cpp DxcReflectionJson.cpp) +add_clang_library(dxcreflectioncontainer STATIC DxcReflectionContainer.cpp DxcReflectionJson.cpp) diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 2c86625855..2c7f45b729 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -571,7 +571,8 @@ static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, } }); - if ((node.IsFwdBckDefined() || node.IsFwdDeclare()) || IsVerbose) { + if (((node.IsFwdBckDefined() || node.IsFwdDeclare()) && AllRelevantMembers) || + IsVerbose) { Json.BoolField("IsFwdDeclare", node.IsFwdDeclare()); Json.BoolField("IsFwdBackDefined", node.IsFwdBckDefined()); @@ -1129,9 +1130,14 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, ReflectionNode node = Reflection.Nodes[NodeId]; + // In case we're a fwd declare, don't change how we walk the tree + + uint32_t nodeChildCountForRet = node.GetChildCount(); + // If this happens, we found the one defining a fwd declare. // But this can happen in a different scope than the symbol ends up in. // Mute this node. + // (This should be checked by the caller to avoid empty objects laying around) if (node.IsFwdBckDefined() && !node.IsFwdDeclare()) return node.GetChildCount(); @@ -1282,6 +1288,14 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, Json.Array(bodyName, [&Reflection, &Json, IsVerbose, start, end, IsHumanFriendly, NodeId]() { for (uint32_t i = start; i < end; ++i) { + + const ReflectionNode &node = Reflection.Nodes[i]; + + if (node.IsFwdBckDefined() && !node.IsFwdDeclare()) { + i += node.GetChildCount(); + continue; + } + JsonWriter::ObjectScope valueRoot(Json); i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, IsHumanFriendly); @@ -1301,6 +1315,14 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, Json.Array(elseName, [&Reflection, &Json, IsVerbose, start, end, IsHumanFriendly, NodeId]() { for (uint32_t i = start; i < end; ++i) { + + const ReflectionNode &node = Reflection.Nodes[i]; + + if (node.IsFwdBckDefined() && !node.IsFwdDeclare()) { + i += node.GetChildCount(); + continue; + } + JsonWriter::ObjectScope valueRoot(Json); i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, IsHumanFriendly); @@ -1331,12 +1353,20 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, Json.Array("Children", [&Reflection, &Json, IsVerbose, start, end, IsHumanFriendly]() { for (uint32_t i = start; i < end; ++i) { + + const ReflectionNode &node = Reflection.Nodes[i]; + + if (node.IsFwdBckDefined() && !node.IsFwdDeclare()) { + i += node.GetChildCount(); + continue; + } + JsonWriter::ObjectScope valueRoot(Json); i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, IsHumanFriendly); } }); - return node.GetChildCount(); + return nodeChildCountForRet; } // IsHumanFriendly = false: Raw view of the real file data @@ -1517,6 +1547,14 @@ std::string ReflectionData::ToJson( else json.Array("Children", [this, &json, IsVerbose]() { for (uint32_t i = 1; i < Nodes.size(); ++i) { + + const ReflectionNode &node = Nodes[i]; + + if (node.IsFwdBckDefined() && !node.IsFwdDeclare()) { + i += node.GetChildCount(); + continue; + } + JsonWriter::ObjectScope valueRoot(json); i += PrintNodeRecursive(*this, i, json, IsVerbose, true); } From 0ef496d6ad65463ddee374be1de9c0b73cde34bd Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 10 Nov 2025 20:42:52 +0100 Subject: [PATCH 094/126] Removed printing BufferId and NameId in human readable mode. Fixed crash when printing nodes if a forward declare had no definition --- .../tools/dxcreflectioncontainer/DxcReflectionJson.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 2c7f45b729..5df23f4c95 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -662,7 +662,7 @@ static void PrintRegister(JsonWriter &Json, const ReflectionData &Reflection, break; } - if (printBufferId || IsVerbose) + if ((printBufferId && AllRelevantMembers) || IsVerbose) Json.UIntField("BufferId", reg.GetBufferId()); if (reg.GetFlags() || IsVerbose) { @@ -787,7 +787,9 @@ static void PrintType(const ReflectionData &Reflection, uint32_t TypeId, if (HasSymbols) { Json.StringField( "Name", Reflection.Strings[Reflection.MemberNameIds[memberId]]); - Json.UIntField("NameId", Reflection.MemberNameIds[memberId]); + + if (AllRelevantMembers || IsVerbose) + Json.UIntField("NameId", Reflection.MemberNameIds[memberId]); } if (Recursive) @@ -1143,7 +1145,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, D3D12_HLSL_NODE_TYPE nodeType = node.GetNodeType(); - if (node.IsFwdDeclare()) { + if (node.IsFwdDeclare() && node.IsFwdBckDefined()) { NodeId = node.GetFwdBck(); node = Reflection.Nodes[NodeId]; } From e3e8015f384f5b03b9dbb589113bf26a477e0472 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 10 Nov 2025 21:05:33 +0100 Subject: [PATCH 095/126] Extended the bitset for the comma stack by 3x, allowing long if/else chains to not break. This will however need to be prevented for readability purposes --- .../dxcreflectioncontainer/DxcReflectionJson.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 5df23f4c95..5154c18d13 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -18,25 +18,29 @@ struct JsonWriter { std::stringstream ss; uint16_t indent = 0; uint16_t countCommaStack = 0; - uint32_t needCommaStack = 0; + uint32_t needCommaStack[3] = {0, 0, 0}; void Indent() { ss << std::string(indent, '\t'); } void NewLine() { ss << "\n"; } void StartCommaStack() { ++countCommaStack; - assert(countCommaStack < 32 && "countCommaStack out of bounds"); - needCommaStack &= ~(1u << countCommaStack); + assert(countCommaStack < 96 && "countCommaStack out of bounds"); + needCommaStack[countCommaStack / 32] &= ~(1u << (countCommaStack & 31)); } - void SetComma() { needCommaStack |= 1u << countCommaStack; } + void SetComma() { + needCommaStack[countCommaStack / 32] |= 1u << (countCommaStack & 31); + } void EndCommaStack() { --countCommaStack; SetComma(); } - bool NeedsComma() { return (needCommaStack >> countCommaStack) & 1; } + bool NeedsComma() { + return (needCommaStack[countCommaStack / 32] >> (countCommaStack & 31)) & 1; + } void BeginObj() { From e28baffc24eb87e4efb02ca00cc946dcc2150074 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 10 Nov 2025 21:33:33 +0100 Subject: [PATCH 096/126] Fixed root node pointing to an invalid source file in case of an empty file --- .../tools/dxcreflection/dxcreflection_from_ast.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index e53dc537b7..8679ad46c6 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -2028,12 +2028,9 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, } [[nodiscard]] ReflectionError DxcHLSLReflectionDataFromAST( - ReflectionData &Result, - CompilerInstance &Compiler, - TranslationUnitDecl &Ctx, - uint32_t AutoBindingSpace, - D3D12_HLSL_REFLECTION_FEATURE Features, - bool DefaultRowMaj) { + ReflectionData &Result, CompilerInstance &Compiler, + TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, + D3D12_HLSL_REFLECTION_FEATURE Features, bool DefaultRowMaj) { DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); const SourceManager &SM = Compiler.getSourceManager(); @@ -2047,7 +2044,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, Result.NodeSymbols.push_back({}); if (ReflectionError err = ReflectionNodeSymbol::Initialize( - Result.NodeSymbols[0], 0, 0, 0, 0, 0, 0)) { + Result.NodeSymbols[0], 0, uint16_t(-1), 0, 0, 0, 0)) { llvm::errs() << "DxcHLSLReflectionDataFromAST: Failed to add root symbol: " << err; Result = {}; From f080ff0e43b0695f363e7a4d42f1ae15b2bd49b4 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 10 Nov 2025 21:58:51 +0100 Subject: [PATCH 097/126] Added ShowFileInfo (-reflect-show-file-info) to ReflectOpts which unhides the file info. Without his option, the JSON becomes very big but could be useful for knowing where certain symbols are. --- .../DxcReflection/DxcReflectionContainer.h | 4 +- include/dxc/Support/HLSLOptions.h | 1 + include/dxc/Support/HLSLOptions.td | 3 + lib/DxcSupport/HLSLOptions.cpp | 2 + .../tools/dxcreflection/dxcreflector.cpp | 4 +- .../DxcReflectionJson.cpp | 106 ++++++++++-------- 6 files changed, 71 insertions(+), 49 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflectionContainer.h b/include/dxc/DxcReflection/DxcReflectionContainer.h index 396ede1b7c..fb7350f193 100644 --- a/include/dxc/DxcReflection/DxcReflectionContainer.h +++ b/include/dxc/DxcReflection/DxcReflectionContainer.h @@ -827,7 +827,9 @@ struct ReflectionData { static D3D_CBUFFER_TYPE GetBufferType(uint8_t Type); void Dump(std::vector &Bytes) const; - std::string ToJson(bool IsHumanFriendly = true, bool IsVerbose = false) const; + std::string ToJson(bool HideFileInfo = false, bool IsHumanFriendly = true, + bool IsVerbose = false) const; + void StripSymbols(); bool GenerateNameLookupTable(); diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index 5d51aaf534..aeef5b1ffe 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -125,6 +125,7 @@ struct ReflectOpts { bool UserTypes = false; // OPT_reflect_user_types bool Scopes = false; // OPT_reflect_scopes bool DisableSymbols = false; // OPT_reflect_disable_symbols + bool ShowFileInfo = false; // OPT_reflect_show_file_info }; /// Use this class to capture all options. diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index 69dd43730b..e5c4db24b3 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -596,6 +596,9 @@ def reflect_scopes : Flag<["-", "/"], "reflect-scopes">, Group, Group, Flags<[ReflectOption]>, HelpText<"Reflect HLSL disable symbols.">; +def reflect_show_file_info : Flag<["-", "/"], "reflect-show-file-info">, Group, Flags<[ReflectOption]>, + HelpText<"Show file symbol info in the reflection output json.">; + ////////////////////////////////////////////////////////////////////////////// // Rewriter Options diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index 0b3e4c95ea..615e80b2fc 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -1385,6 +1385,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, opts.ReflOpt.Scopes = Args.hasFlag(OPT_reflect_scopes, OPT_INVALID, false); opts.ReflOpt.DisableSymbols = Args.hasFlag(OPT_reflect_disable_symbols, OPT_INVALID, false); + opts.ReflOpt.ShowFileInfo = + Args.hasFlag(OPT_reflect_show_file_info, OPT_INVALID, false); } opts.Args = std::move(Args); diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 6033c4f3ae..23a34c87ac 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -1605,7 +1605,9 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, return E_FAIL; } - printf("%s\n", refl.ToJson().c_str()); + bool hideFileInfo = !opts.ReflOpt.ShowFileInfo; + + printf("%s\n", refl.ToJson(hideFileInfo).c_str()); // Debug: Verify deserialization, otherwise print error. diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 5154c18d13..df5af997d1 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -473,7 +473,8 @@ static void FillArraySizes(const ReflectionData &Reflection, static void PrintSymbol(JsonWriter &Json, const ReflectionData &Reflection, const ReflectionNodeSymbol &Sym, bool IsVerbose, - bool AllRelevantMembers, bool MuteName = false) { + bool AllRelevantMembers, bool HideFileInfo, + bool MuteName) { if ((Sym.GetNameId() || IsVerbose) && !MuteName) { @@ -483,6 +484,9 @@ static void PrintSymbol(JsonWriter &Json, Json.UIntField("NameId", Sym.GetNameId()); } + if (HideFileInfo) + return; + if (Sym.HasFileSource()) { Json.StringField( @@ -517,7 +521,8 @@ static void PrintSymbol(JsonWriter &Json, // Verbose will still print fields even if they aren't relevant, // while all members will not silence important info but that might not matter for human readability static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t NodeId, bool IsVerbose, bool AllRelevantMembers) { + uint32_t NodeId, bool IsVerbose, bool AllRelevantMembers, + bool HideFileInfo) { const ReflectionNode &node = Reflection.Nodes[NodeId]; @@ -589,9 +594,10 @@ static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, if (hasSymbols) { Json.Object("Symbol", [&Reflection, &Json, NodeId, IsVerbose, - AllRelevantMembers] { + AllRelevantMembers, HideFileInfo] { const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; - PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers); + PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers, + HideFileInfo, false); }); } else if (IsVerbose) @@ -854,7 +860,7 @@ static void PrintParameter(const ReflectionData &Reflection, uint32_t TypeId, static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, uint32_t FunctionId, bool IsVerbose, - bool AllRelevantMembers) { + bool AllRelevantMembers, bool HideFileInfo) { const ReflectionFunction &func = Reflection.Functions[FunctionId]; @@ -877,7 +883,8 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, Json.StringField("Name", ""); } - Json.BoolField("HasDefinition", func.HasDefinition()); + if (!func.HasDefinition() || AllRelevantMembers) + Json.BoolField("HasDefinition", func.HasDefinition()); if (IsVerbose) { Json.UIntField("NumParameters", func.GetNumParameters()); @@ -885,7 +892,7 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, } Json.Object("Params", [&Reflection, &func, &Json, hasSymbols, IsVerbose, - AllRelevantMembers]() { + AllRelevantMembers, HideFileInfo]() { for (uint32_t i = 0; i < uint32_t(func.GetNumParameters()); ++i) { uint32_t nodeId = func.GetNodeId() + 1 + i; @@ -900,16 +907,17 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, Json.Object(paramName.c_str(), [&Reflection, &func, &Json, hasSymbols, IsVerbose, ¶m, &node, - AllRelevantMembers, nodeId]() { + AllRelevantMembers, nodeId, + HideFileInfo]() { - if (hasSymbols) { + if (hasSymbols && !HideFileInfo) { const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[nodeId]; Json.Object("Symbol", [&Json, &Reflection, &sym, IsVerbose, - AllRelevantMembers]() { + AllRelevantMembers, HideFileInfo]() { PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers, - true); + HideFileInfo, true); }); } @@ -953,7 +961,7 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, static void PrintEnumValue(JsonWriter &Json, const ReflectionData &Reflection, uint32_t NodeId, bool IsVerbose, - bool AllRelevantMembers) { + bool AllRelevantMembers, bool HideFileInfo) { const ReflectionNode &child = Reflection.Nodes[NodeId]; @@ -980,9 +988,9 @@ static void PrintEnumValue(JsonWriter &Json, const ReflectionData &Reflection, const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; - Json.Object( - "Symbol", [&Json, &Reflection, &sym, IsVerbose, AllRelevantMembers]() { - PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers); + Json.Object("Symbol", [&Json, &Reflection, &sym, IsVerbose, + AllRelevantMembers, HideFileInfo]() { + PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers, HideFileInfo, false); }); } @@ -991,8 +999,8 @@ static void PrintEnumValue(JsonWriter &Json, const ReflectionData &Reflection, } static void PrintEnum(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t EnumId, bool IsVerbose, - bool AllRelevantMembers) { + uint32_t EnumId, bool IsVerbose, bool AllRelevantMembers, + bool HideFileInfo) { const ReflectionEnumeration &enm = Reflection.Enums[EnumId]; const ReflectionNode &node = Reflection.Nodes[enm.NodeId]; @@ -1016,7 +1024,7 @@ static void PrintEnum(JsonWriter &Json, const ReflectionData &Reflection, Json.StringField("EnumType", EnumTypeToString(enm.Type)); Json.Array("Values", [&Json, &node, &enm, hasSymbols, &Reflection, IsVerbose, - AllRelevantMembers]() { + AllRelevantMembers, HideFileInfo]() { for (uint32_t i = 0; i < node.GetChildCount(); ++i) { uint32_t childId = enm.NodeId + 1 + i; @@ -1026,7 +1034,7 @@ static void PrintEnum(JsonWriter &Json, const ReflectionData &Reflection, if (!hasSymbols || AllRelevantMembers || IsVerbose) Json.UIntField("ValueId", i); - PrintEnumValue(Json, Reflection, childId, IsVerbose, AllRelevantMembers); + PrintEnumValue(Json, Reflection, childId, IsVerbose, AllRelevantMembers, HideFileInfo); } }); } @@ -1126,7 +1134,7 @@ static void PrintStatement(const ReflectionData &Reflection, uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, JsonWriter &Json, bool IsVerbose, - bool IsHumanFriendly) { + bool IsHumanFriendly, bool HideFileInfo) { bool hasSymbols = @@ -1154,7 +1162,8 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, node = Reflection.Nodes[NodeId]; } - PrintNode(Json, Reflection, NodeId, IsVerbose, !IsHumanFriendly); + PrintNode(Json, Reflection, NodeId, IsVerbose, !IsHumanFriendly, + HideFileInfo); uint32_t childrenToSkip = 0; @@ -1162,10 +1171,10 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, if (nodeType == D3D12_HLSL_NODE_TYPE_FUNCTION) Json.Object("Function", [&node, &Reflection, &Json, IsVerbose, - IsHumanFriendly, &childrenToSkip]() { + IsHumanFriendly, &childrenToSkip, HideFileInfo]() { ReflectionFunction func = Reflection.Functions[node.GetLocalId()]; PrintFunction(Json, Reflection, node.GetLocalId(), IsVerbose, - !IsHumanFriendly); + !IsHumanFriendly, HideFileInfo); childrenToSkip = func.GetNumParameters() + func.HasReturn(); }); @@ -1188,9 +1197,9 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, if (nodeType == D3D12_HLSL_NODE_TYPE_ENUM) Json.Object("Enum", [&node, &Reflection, &Json, IsVerbose, IsHumanFriendly, - &childrenToSkip]() { + &childrenToSkip, HideFileInfo]() { PrintEnum(Json, Reflection, node.GetLocalId(), IsVerbose, - !IsHumanFriendly); + !IsHumanFriendly, HideFileInfo); childrenToSkip = node.GetChildCount(); }); @@ -1269,16 +1278,17 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, } Json.Object(stmtType, [&node, &Reflection, &Json, IsVerbose, - IsHumanFriendly, NodeId, &childrenToSkip, nodeType]() { + IsHumanFriendly, NodeId, &childrenToSkip, nodeType, + HideFileInfo]() { const ReflectionScopeStmt &stmt = Reflection.Statements[node.GetLocalId()]; uint32_t start = NodeId + 1; if (stmt.HasConditionVar()) Json.Object("Condition", [NodeId, &Reflection, &Json, IsVerbose, - IsHumanFriendly, &start]() { + IsHumanFriendly, &start, HideFileInfo]() { start += PrintNodeRecursive(Reflection, start, Json, IsVerbose, - IsHumanFriendly); + IsHumanFriendly, HideFileInfo); ++start; }); @@ -1292,7 +1302,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, if (stmt.GetNodeCount()) Json.Array(bodyName, [&Reflection, &Json, IsVerbose, start, end, - IsHumanFriendly, NodeId]() { + IsHumanFriendly, NodeId, HideFileInfo]() { for (uint32_t i = start; i < end; ++i) { const ReflectionNode &node = Reflection.Nodes[i]; @@ -1304,7 +1314,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, JsonWriter::ObjectScope valueRoot(Json); i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, - IsHumanFriendly); + IsHumanFriendly, HideFileInfo); } }); @@ -1319,7 +1329,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, end = NodeId + 1 + node.GetChildCount(); Json.Array(elseName, [&Reflection, &Json, IsVerbose, start, end, - IsHumanFriendly, NodeId]() { + IsHumanFriendly, NodeId, HideFileInfo]() { for (uint32_t i = start; i < end; ++i) { const ReflectionNode &node = Reflection.Nodes[i]; @@ -1331,7 +1341,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, JsonWriter::ObjectScope valueRoot(Json); i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, - IsHumanFriendly); + IsHumanFriendly, HideFileInfo); } }); } @@ -1357,7 +1367,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, if (end > start) Json.Array("Children", [&Reflection, &Json, IsVerbose, start, end, - IsHumanFriendly]() { + IsHumanFriendly, HideFileInfo]() { for (uint32_t i = start; i < end; ++i) { const ReflectionNode &node = Reflection.Nodes[i]; @@ -1368,7 +1378,8 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, } JsonWriter::ObjectScope valueRoot(Json); - i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, IsHumanFriendly); + i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, IsHumanFriendly, + HideFileInfo); } }); @@ -1377,8 +1388,8 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, // IsHumanFriendly = false: Raw view of the real file data // IsHumanFriendly = true: Clean view that's relatively close to the real tree -std::string ReflectionData::ToJson( - bool IsHumanFriendly, bool IsVerbose) const { +std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly, + bool IsVerbose) const { JsonWriter json; @@ -1416,10 +1427,10 @@ std::string ReflectionData::ToJson( json.Value(uint64_t(id)); }); - json.Array("Nodes", [this, &json, IsVerbose] { + json.Array("Nodes", [this, &json, IsVerbose, HideFileInfo] { for (uint32_t i = 0; i < uint32_t(Nodes.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintNode(json, *this, i, IsVerbose, true); + PrintNode(json, *this, i, IsVerbose, true, HideFileInfo); } }); @@ -1430,10 +1441,10 @@ std::string ReflectionData::ToJson( } }); - json.Array("Functions", [this, &json, IsVerbose] { + json.Array("Functions", [this, &json, IsVerbose, HideFileInfo] { for (uint32_t i = 0; i < uint32_t(Functions.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintFunction(json, *this, i, IsVerbose, true); + PrintFunction(json, *this, i, IsVerbose, true, HideFileInfo); } }); @@ -1458,18 +1469,19 @@ std::string ReflectionData::ToJson( } }); - json.Array("Enums", [this, &json, hasSymbols, IsVerbose] { + json.Array("Enums", [this, &json, hasSymbols, IsVerbose, HideFileInfo] { for (uint32_t i = 0; i < uint32_t(Enums.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintEnum(json, *this, i, IsVerbose, true); + PrintEnum(json, *this, i, IsVerbose, true, HideFileInfo); } }); - json.Array("EnumValues", [this, &json, hasSymbols, IsVerbose] { + json.Array("EnumValues", [this, &json, hasSymbols, IsVerbose, + HideFileInfo] { for (uint32_t i = 0; i < uint32_t(EnumValues.size()); ++i) { JsonWriter::ObjectScope valueRoot(json); - PrintEnumValue(json, *this, EnumValues[i].NodeId, - IsVerbose, true); + PrintEnumValue(json, *this, EnumValues[i].NodeId, IsVerbose, true, + HideFileInfo); } }); @@ -1551,7 +1563,7 @@ std::string ReflectionData::ToJson( } else - json.Array("Children", [this, &json, IsVerbose]() { + json.Array("Children", [this, &json, IsVerbose, HideFileInfo]() { for (uint32_t i = 1; i < Nodes.size(); ++i) { const ReflectionNode &node = Nodes[i]; @@ -1562,7 +1574,7 @@ std::string ReflectionData::ToJson( } JsonWriter::ObjectScope valueRoot(json); - i += PrintNodeRecursive(*this, i, json, IsVerbose, true); + i += PrintNodeRecursive(*this, i, json, IsVerbose, true, HideFileInfo); } }); } From 7e635a6782f93a6c6b906c3e91d25bc6ea004d16 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 10 Nov 2025 23:20:05 +0100 Subject: [PATCH 098/126] Added PrintChildren to handle printing recursive children. --- .../DxcReflectionJson.cpp | 110 +++++++----------- 1 file changed, 44 insertions(+), 66 deletions(-) diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index df5af997d1..48d97ae599 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -591,13 +591,13 @@ static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, !node.IsFwdBckDefined() ? -1 : int64_t(node.GetFwdBck())); } - if (hasSymbols) { + if (hasSymbols && !HideFileInfo) { Json.Object("Symbol", [&Reflection, &Json, NodeId, IsVerbose, AllRelevantMembers, HideFileInfo] { const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers, - HideFileInfo, false); + HideFileInfo, true); }); } else if (IsVerbose) @@ -1132,6 +1132,39 @@ static void PrintStatement(const ReflectionData &Reflection, Json.UIntField("NodesB", nodesB); } +uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, + JsonWriter &Json, bool IsVerbose, + bool IsHumanFriendly, bool HideFileInfo); + +void PrintChildren(const ReflectionData &Data, JsonWriter &Json, + const char *ObjectName, uint32_t Start, uint32_t End, + bool IsVerbose, bool HideFileInfo, bool IsHumanFriendly) { + + if (End > Start) + Json.Array(ObjectName, [&Data, &Json, Start, End, IsVerbose, HideFileInfo, + IsHumanFriendly]() { + for (uint32_t i = Start; i < End; ++i) { + + const ReflectionNode &node = Data.Nodes[i]; + + if (node.IsFwdBckDefined() && !node.IsFwdDeclare()) { + i += node.GetChildCount(); + continue; + } + + JsonWriter::ObjectScope scope(Json); + + // Put Name(Id) into current scope to hide "Symbol" everywhere. + + if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) + PrintSymbol(Json, Data, Data.NodeSymbols[i], false, + !IsHumanFriendly, true, false); + + i += PrintNodeRecursive(Data, i, Json, IsVerbose, true, HideFileInfo); + } + }); +} + uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, JsonWriter &Json, bool IsVerbose, bool IsHumanFriendly, bool HideFileInfo) { @@ -1301,22 +1334,8 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, const char *bodyName = isIf ? "Body" : "Init"; if (stmt.GetNodeCount()) - Json.Array(bodyName, [&Reflection, &Json, IsVerbose, start, end, - IsHumanFriendly, NodeId, HideFileInfo]() { - for (uint32_t i = start; i < end; ++i) { - - const ReflectionNode &node = Reflection.Nodes[i]; - - if (node.IsFwdBckDefined() && !node.IsFwdDeclare()) { - i += node.GetChildCount(); - continue; - } - - JsonWriter::ObjectScope valueRoot(Json); - i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, - IsHumanFriendly, HideFileInfo); - } - }); + PrintChildren(Reflection, Json, bodyName, start, end, IsVerbose, + HideFileInfo, IsHumanFriendly); else if (IsVerbose) Json.NullField(bodyName); @@ -1328,22 +1347,8 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, start = end; end = NodeId + 1 + node.GetChildCount(); - Json.Array(elseName, [&Reflection, &Json, IsVerbose, start, end, - IsHumanFriendly, NodeId, HideFileInfo]() { - for (uint32_t i = start; i < end; ++i) { - - const ReflectionNode &node = Reflection.Nodes[i]; - - if (node.IsFwdBckDefined() && !node.IsFwdDeclare()) { - i += node.GetChildCount(); - continue; - } - - JsonWriter::ObjectScope valueRoot(Json); - i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, - IsHumanFriendly, HideFileInfo); - } - }); + PrintChildren(Reflection, Json, elseName, start, end, IsVerbose, + HideFileInfo, IsHumanFriendly); } else if (IsVerbose) @@ -1364,25 +1369,10 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t start = NodeId + 1 + childrenToSkip; uint32_t end = NodeId + 1 + node.GetChildCount(); - - if (end > start) - Json.Array("Children", [&Reflection, &Json, IsVerbose, start, end, - IsHumanFriendly, HideFileInfo]() { - for (uint32_t i = start; i < end; ++i) { - - const ReflectionNode &node = Reflection.Nodes[i]; - - if (node.IsFwdBckDefined() && !node.IsFwdDeclare()) { - i += node.GetChildCount(); - continue; - } - - JsonWriter::ObjectScope valueRoot(Json); - i += PrintNodeRecursive(Reflection, i, Json, IsVerbose, IsHumanFriendly, - HideFileInfo); - } - }); + PrintChildren(Reflection, Json, "Children", start, end, IsVerbose, + HideFileInfo, IsHumanFriendly); + return nodeChildCountForRet; } @@ -1563,20 +1553,8 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly, } else - json.Array("Children", [this, &json, IsVerbose, HideFileInfo]() { - for (uint32_t i = 1; i < Nodes.size(); ++i) { - - const ReflectionNode &node = Nodes[i]; - - if (node.IsFwdBckDefined() && !node.IsFwdDeclare()) { - i += node.GetChildCount(); - continue; - } - - JsonWriter::ObjectScope valueRoot(json); - i += PrintNodeRecursive(*this, i, json, IsVerbose, true, HideFileInfo); - } - }); + PrintChildren(*this, json, "Children", 1, Nodes.size(), IsVerbose, + HideFileInfo, true); } return json.str(); From 3c80ff835178592ac245bdb79aefe8c5667cf324 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 10 Nov 2025 23:55:12 +0100 Subject: [PATCH 099/126] Removed IsVerbose since it'll never get used and overcomplicates printing. Added reflect-show-raw-data to show raw reflection data dump as json without pretty printing. --- .../DxcReflection/DxcReflectionContainer.h | 13 +- include/dxc/Support/HLSLOptions.h | 1 + include/dxc/Support/HLSLOptions.td | 3 + lib/DxcSupport/HLSLOptions.cpp | 2 + .../tools/dxcreflection/dxcreflector.cpp | 3 +- .../DxcReflectionJson.cpp | 463 +++++++----------- 6 files changed, 183 insertions(+), 302 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflectionContainer.h b/include/dxc/DxcReflection/DxcReflectionContainer.h index fb7350f193..93dc21a440 100644 --- a/include/dxc/DxcReflection/DxcReflectionContainer.h +++ b/include/dxc/DxcReflection/DxcReflectionContainer.h @@ -817,25 +817,26 @@ struct ReflectionData { [[nodiscard]] ReflectionError RegisterString(uint32_t &StringId, const std::string &Name, bool IsNonDebug); - [[nodiscard]] ReflectionError PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, - const std::vector &ArraySize); + [[nodiscard]] ReflectionError + PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, + const std::vector &ArraySize); [[nodiscard]] ReflectionError RegisterTypeList(const std::vector &TypeIds, uint32_t &Offset, - uint8_t &Len); + uint8_t &Len); static D3D_CBUFFER_TYPE GetBufferType(uint8_t Type); void Dump(std::vector &Bytes) const; - std::string ToJson(bool HideFileInfo = false, bool IsHumanFriendly = true, - bool IsVerbose = false) const; + std::string ToJson(bool HideFileInfo = false, + bool IsHumanFriendly = true) const; void StripSymbols(); bool GenerateNameLookupTable(); ReflectionData() = default; [[nodiscard]] ReflectionError Deserialize(const std::vector &Bytes, - bool MakeNameLookupTable); + bool MakeNameLookupTable); bool IsSameNonDebug(const ReflectionData &Other) const { return StringsNonDebug == Other.StringsNonDebug && Nodes == Other.Nodes && diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index aeef5b1ffe..f253830b62 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -126,6 +126,7 @@ struct ReflectOpts { bool Scopes = false; // OPT_reflect_scopes bool DisableSymbols = false; // OPT_reflect_disable_symbols bool ShowFileInfo = false; // OPT_reflect_show_file_info + bool ShowRawData = false; // OPT_reflect_show_raw_data }; /// Use this class to capture all options. diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index e5c4db24b3..49aab4bce5 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -599,6 +599,9 @@ def reflect_disable_symbols : Flag<["-", "/"], "reflect-disable-symbols">, Group def reflect_show_file_info : Flag<["-", "/"], "reflect-show-file-info">, Group, Flags<[ReflectOption]>, HelpText<"Show file symbol info in the reflection output json.">; +def reflect_show_raw_data : Flag<["-", "/"], "reflect-show-raw-data">, Group, Flags<[ReflectOption]>, + HelpText<"Show raw data without prettifying in the reflection output json.">; + ////////////////////////////////////////////////////////////////////////////// // Rewriter Options diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index 615e80b2fc..ea753e6520 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -1387,6 +1387,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, Args.hasFlag(OPT_reflect_disable_symbols, OPT_INVALID, false); opts.ReflOpt.ShowFileInfo = Args.hasFlag(OPT_reflect_show_file_info, OPT_INVALID, false); + opts.ReflOpt.ShowRawData = + Args.hasFlag(OPT_reflect_show_raw_data, OPT_INVALID, false); } opts.Args = std::move(Args); diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 23a34c87ac..725ee3ee91 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -1606,8 +1606,9 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, } bool hideFileInfo = !opts.ReflOpt.ShowFileInfo; + bool humanFriendly = !opts.ReflOpt.ShowRawData; - printf("%s\n", refl.ToJson(hideFileInfo).c_str()); + printf("%s\n", refl.ToJson(hideFileInfo, humanFriendly).c_str()); // Debug: Verify deserialization, otherwise print error. diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 48d97ae599..62217b1676 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -472,15 +472,15 @@ static void FillArraySizes(const ReflectionData &Reflection, static void PrintSymbol(JsonWriter &Json, const ReflectionData &Reflection, - const ReflectionNodeSymbol &Sym, bool IsVerbose, + const ReflectionNodeSymbol &Sym, bool AllRelevantMembers, bool HideFileInfo, bool MuteName) { - if ((Sym.GetNameId() || IsVerbose) && !MuteName) { + if (Sym.GetNameId() && !MuteName) { Json.StringField("Name", Reflection.Strings[Sym.GetNameId()]); - if (IsVerbose || AllRelevantMembers) + if (AllRelevantMembers) Json.UIntField("NameId", Sym.GetNameId()); } @@ -493,27 +493,16 @@ static void PrintSymbol(JsonWriter &Json, "Source", Reflection.Strings[Reflection.Sources[Sym.GetFileSourceId()]]); - if (IsVerbose || AllRelevantMembers) + if (AllRelevantMembers) Json.UIntField("SourceId", Sym.GetFileSourceId()); Json.UIntField("LineId", Sym.GetSourceLineStart()); - if (Sym.GetSourceLineCount() > 1 || IsVerbose) + if (Sym.GetSourceLineCount() > 1) Json.UIntField("LineCount", Sym.GetSourceLineCount()); Json.UIntField("ColumnStart", Sym.GetSourceColumnStart()); Json.UIntField("ColumnEnd", Sym.GetSourceColumnEnd()); - - } else if (IsVerbose) { - - Json.StringField("Source", ""); - Json.IntField("SourceId", -1); - - Json.IntField("LineId", -1); - Json.UIntField("LineCount", 0); - - Json.IntField("ColumnStart", -1); - Json.UIntField("ColumnEnd", 0); } } @@ -521,7 +510,7 @@ static void PrintSymbol(JsonWriter &Json, // Verbose will still print fields even if they aren't relevant, // while all members will not silence important info but that might not matter for human readability static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t NodeId, bool IsVerbose, bool AllRelevantMembers, + uint32_t NodeId, bool AllRelevantMembers, bool HideFileInfo) { const ReflectionNode &node = Reflection.Nodes[NodeId]; @@ -529,12 +518,12 @@ static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (AllRelevantMembers || IsVerbose || !hasSymbols) + if (AllRelevantMembers || !hasSymbols) Json.UIntField("NodeId", NodeId); Json.StringField("NodeType", NodeTypeToString(node.GetNodeType())); - if (IsVerbose || AllRelevantMembers) { + if (AllRelevantMembers) { Json.UIntField("NodeTypeId", node.GetNodeType()); Json.UIntField("LocalId", node.GetLocalId()); Json.IntField("ParentId", node.GetParentId() == uint16_t(-1) @@ -542,26 +531,27 @@ static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, : int64_t(node.GetParentId())); } - if (IsVerbose || (node.GetChildCount() && AllRelevantMembers)) { + if (node.GetChildCount() && AllRelevantMembers) { Json.UIntField("ChildCount", node.GetChildCount()); Json.UIntField("ChildStart", NodeId + 1); } - if (node.GetSemanticId() != uint32_t(-1) || IsVerbose) - Json.StringField("Semantic", - node.GetSemanticId() != uint32_t(-1) - ? Reflection.StringsNonDebug[node.GetSemanticId()] - : ""); + if (node.GetSemanticId() != uint32_t(-1)) { - if (IsVerbose || (AllRelevantMembers && node.GetSemanticId() != uint32_t(-1))) - Json.IntField("SemanticId", node.GetSemanticId() == uint32_t(-1) ? -1 : int64_t(node.GetSemanticId())); + Json.StringField("Semantic", + Reflection.StringsNonDebug[node.GetSemanticId()]); - if (IsVerbose || (AllRelevantMembers && node.GetAnnotationCount())) { - Json.UIntField("AnnotationStart", node.GetAnnotationStart()); - Json.UIntField("AnnotationCount", node.GetAnnotationCount()); + if (AllRelevantMembers) + Json.UIntField("SemanticId", node.GetSemanticId()); } - if (node.GetAnnotationCount() || IsVerbose) + if (node.GetAnnotationCount()) { + + if (AllRelevantMembers) { + Json.UIntField("AnnotationStart", node.GetAnnotationStart()); + Json.UIntField("AnnotationCount", node.GetAnnotationCount()); + } + Json.Array("Annotations", [&Reflection, &Json, node] { for (uint32_t i = 0; i < node.GetAnnotationCount(); ++i) { @@ -579,78 +569,59 @@ static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, Json.Value(name); } }); + } - if (((node.IsFwdBckDefined() || node.IsFwdDeclare()) && AllRelevantMembers) || - IsVerbose) { - + if ((node.IsFwdBckDefined() || node.IsFwdDeclare()) && AllRelevantMembers) { Json.BoolField("IsFwdDeclare", node.IsFwdDeclare()); - Json.BoolField("IsFwdBackDefined", node.IsFwdBckDefined()); - - if (node.IsFwdBckDefined() || IsVerbose) - Json.IntField("FwdBack", - !node.IsFwdBckDefined() ? -1 : int64_t(node.GetFwdBck())); + Json.IntField("FwdBack", + !node.IsFwdBckDefined() ? -1 : int64_t(node.GetFwdBck())); } - if (hasSymbols && !HideFileInfo) { - - Json.Object("Symbol", [&Reflection, &Json, NodeId, IsVerbose, + if (hasSymbols && !HideFileInfo) + Json.Object("Symbol", [&Reflection, &Json, NodeId, AllRelevantMembers, HideFileInfo] { const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; - PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers, + PrintSymbol(Json, Reflection, sym, AllRelevantMembers, HideFileInfo, true); }); - - } else if (IsVerbose) - Json.NullField("Symbol"); } static void PrintRegister(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t RegisterId, bool IsVerbose, - bool AllRelevantMembers) { + uint32_t RegisterId, bool AllRelevantMembers) { const ReflectionShaderResource ® = Reflection.Registers[RegisterId]; bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (IsVerbose || AllRelevantMembers || !hasSymbols) { + if (AllRelevantMembers || !hasSymbols) { Json.UIntField("RegisterId", RegisterId); Json.UIntField("NodeId", reg.GetNodeId()); } - if (AllRelevantMembers) { - - if (hasSymbols) - Json.StringField( - "Name", - Reflection - .Strings[Reflection.NodeSymbols[reg.GetNodeId()].GetNameId()]); - - else if (IsVerbose) - Json.StringField("Name", ""); - } + if (AllRelevantMembers && hasSymbols) + Json.StringField( + "Name", + Reflection + .Strings[Reflection.NodeSymbols[reg.GetNodeId()].GetNameId()]); Json.StringField("RegisterType", RegisterTypeToString(reg.GetType())); - if (reg.GetDimension() != D3D_SRV_DIMENSION_UNKNOWN || IsVerbose) + if (reg.GetDimension() != D3D_SRV_DIMENSION_UNKNOWN) Json.StringField("Dimension", DimensionTypeToString(reg.GetDimension())); - if (reg.GetReturnType() || IsVerbose) + if (reg.GetReturnType()) Json.StringField("ReturnType", ReturnTypeToString(reg.GetReturnType())); - if (reg.GetBindCount() > 1 || IsVerbose) + if (reg.GetBindCount() > 1) Json.UIntField("BindCount", reg.GetBindCount()); - if (reg.GetArrayId() != uint32_t(-1) || IsVerbose) { + if (reg.GetArrayId() != uint32_t(-1)) { - if (IsVerbose || AllRelevantMembers) + if (AllRelevantMembers) Json.UIntField("ArrayId", reg.GetArrayId()); Json.Array("ArraySize", [&Reflection, ®, &Json]() { - - if (reg.GetArrayId() == uint32_t(-1)) - return; - const ReflectionArray &arr = Reflection.Arrays[reg.GetArrayId()]; for (uint32_t i = 0; i < uint32_t(arr.ArrayElem()); ++i) @@ -672,13 +643,11 @@ static void PrintRegister(JsonWriter &Json, const ReflectionData &Reflection, break; } - if ((printBufferId && AllRelevantMembers) || IsVerbose) + if (printBufferId && AllRelevantMembers) Json.UIntField("BufferId", reg.GetBufferId()); - if (reg.GetFlags() || IsVerbose) { - + if (reg.GetFlags()) Json.Array("Flags", [®, &Json]() { - uint32_t flag = reg.GetFlags(); if (flag & D3D_SIF_USERPACKED) @@ -696,15 +665,14 @@ static void PrintRegister(JsonWriter &Json, const ReflectionData &Reflection, if (flag & D3D_SIF_UNUSED) Json.Value("Unused"); }); - } } static void PrintTypeName(const ReflectionData &Reflection, uint32_t TypeId, - bool HasSymbols, bool IsVerbose, - bool AllRelevantMembers, JsonWriter &Json, + bool HasSymbols, bool AllRelevantMembers, + JsonWriter &Json, const char *NameForTypeName = "Name") { - if (AllRelevantMembers || IsVerbose || !HasSymbols) + if (AllRelevantMembers || !HasSymbols) Json.UIntField("TypeId", TypeId); std::string name; @@ -728,19 +696,19 @@ static void PrintTypeName(const ReflectionData &Reflection, uint32_t TypeId, FillArraySizes(Reflection, type.GetUnderlyingArray(), underlyingArraySizes); } - if (name.size() || IsVerbose) + if (name.size()) Json.StringField(NameForTypeName, name); - if (arraySizes.size() || IsVerbose) + if (arraySizes.size()) Json.Array("ArraySize", [&arraySizes, &Json]() { for (uint32_t i : arraySizes) Json.Value(uint64_t(i)); }); - if ((underlyingName.size() && underlyingName != name) || IsVerbose) + if (underlyingName.size() && underlyingName != name) Json.StringField("UnderlyingName", underlyingName); - if ((underlyingArraySizes.size() && underlyingArraySizes != arraySizes) || IsVerbose) + if (underlyingArraySizes.size() && underlyingArraySizes != arraySizes) Json.Array("UnderlyingArraySize", [&underlyingArraySizes, &Json]() { for (uint32_t i : underlyingArraySizes) Json.Value(uint64_t(i)); @@ -748,46 +716,40 @@ static void PrintTypeName(const ReflectionData &Reflection, uint32_t TypeId, } static void PrintType(const ReflectionData &Reflection, uint32_t TypeId, - bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, + bool HasSymbols, bool AllRelevantMembers, JsonWriter &Json, bool Recursive, const char *NameForTypeName = "Name") { const ReflectionVariableType &type = Reflection.Types[TypeId]; - PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, - Json, NameForTypeName); + PrintTypeName(Reflection, TypeId, HasSymbols, AllRelevantMembers, Json, + NameForTypeName); if (type.GetBaseClass() != uint32_t(-1)) - Json.Object("BaseClass", [&Reflection, &Json, &type, HasSymbols, IsVerbose, + Json.Object("BaseClass", [&Reflection, &Json, &type, HasSymbols, AllRelevantMembers, Recursive]() { if (Recursive) - PrintType(Reflection, type.GetBaseClass(), HasSymbols, IsVerbose, + PrintType(Reflection, type.GetBaseClass(), HasSymbols, AllRelevantMembers, Json, true, "TypeName"); else - PrintTypeName(Reflection, type.GetBaseClass(), HasSymbols, IsVerbose, + PrintTypeName(Reflection, type.GetBaseClass(), HasSymbols, AllRelevantMembers, Json, "TypeName"); }); - else if (IsVerbose) - Json.NullField("BaseClass"); - if (type.GetInterfaceCount()) - Json.Array("Interfaces", [&Reflection, &Json, &type, HasSymbols, IsVerbose, + Json.Array("Interfaces", [&Reflection, &Json, &type, HasSymbols, AllRelevantMembers]() { for (uint32_t i = 0; i < uint32_t(type.GetInterfaceCount()); ++i) { uint32_t interfaceId = type.GetInterfaceStart() + i; JsonWriter::ObjectScope nodeRoot(Json); PrintTypeName(Reflection, Reflection.TypeList[interfaceId], HasSymbols, - IsVerbose, AllRelevantMembers, Json); + AllRelevantMembers, Json); } }); - else if (IsVerbose) - Json.NullField("Interfaces"); - if (type.GetMemberCount()) - Json.Array("Members", [&Reflection, &Json, &type, HasSymbols, IsVerbose, + Json.Array("Members", [&Reflection, &Json, &type, HasSymbols, AllRelevantMembers, Recursive]() { for (uint32_t i = 0; i < uint32_t(type.GetMemberCount()); ++i) { @@ -798,40 +760,35 @@ static void PrintType(const ReflectionData &Reflection, uint32_t TypeId, Json.StringField( "Name", Reflection.Strings[Reflection.MemberNameIds[memberId]]); - if (AllRelevantMembers || IsVerbose) + if (AllRelevantMembers) Json.UIntField("NameId", Reflection.MemberNameIds[memberId]); } if (Recursive) PrintType(Reflection, Reflection.MemberTypeIds[memberId], HasSymbols, - IsVerbose, AllRelevantMembers, Json, true, "TypeName"); + AllRelevantMembers, Json, true, "TypeName"); else PrintTypeName(Reflection, Reflection.MemberTypeIds[memberId], - HasSymbols, IsVerbose, AllRelevantMembers, Json, - "TypeName"); + HasSymbols, AllRelevantMembers, Json, "TypeName"); } }); - - else if (IsVerbose) - Json.NullField("Members"); } static void PrintParameter(const ReflectionData &Reflection, uint32_t TypeId, - bool HasSymbols, bool IsVerbose, JsonWriter &Json, + bool HasSymbols, JsonWriter &Json, uint32_t SemanticId, uint8_t InterpolationMode, uint8_t Flags, bool AllRelevantMembers) { - PrintTypeName(Reflection, TypeId, HasSymbols, IsVerbose, AllRelevantMembers, Json, "TypeName"); + PrintTypeName(Reflection, TypeId, HasSymbols, AllRelevantMembers, Json, "TypeName"); - if (SemanticId != uint32_t(-1) || IsVerbose) - Json.StringField("Semantic", SemanticId == uint32_t(-1) - ? "" - : Reflection.StringsNonDebug[SemanticId]); + if (SemanticId != uint32_t(-1)) { - if (IsVerbose || (AllRelevantMembers && SemanticId != uint32_t(-1))) - Json.IntField("SemanticId", - SemanticId == uint32_t(-1) ? -1 : int64_t(SemanticId)); + Json.StringField("Semantic", Reflection.StringsNonDebug[SemanticId]); + + if (AllRelevantMembers) + Json.UIntField("SemanticId", SemanticId); + } if ((Flags & (D3D_PF_IN | D3D_PF_OUT)) == (D3D_PF_IN | D3D_PF_OUT)) Json.StringField("Access", "inout"); @@ -842,9 +799,6 @@ static void PrintParameter(const ReflectionData &Reflection, uint32_t TypeId, else if (Flags & D3D_PF_OUT) Json.StringField("Access", "out"); - else if (IsVerbose) - Json.StringField("Access", "in"); - static const char *interpolationModes[] = {"Undefined", "Constant", "Linear", @@ -854,44 +808,34 @@ static void PrintParameter(const ReflectionData &Reflection, uint32_t TypeId, "LinearSample", "LinearNoperspectiveSample"}; - if (InterpolationMode || IsVerbose) + if (InterpolationMode) Json.StringField("Interpolation", interpolationModes[InterpolationMode]); } static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t FunctionId, bool IsVerbose, - bool AllRelevantMembers, bool HideFileInfo) { + uint32_t FunctionId, bool AllRelevantMembers, + bool HideFileInfo) { const ReflectionFunction &func = Reflection.Functions[FunctionId]; bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (AllRelevantMembers || IsVerbose || !hasSymbols) { + if (AllRelevantMembers || !hasSymbols) { Json.UIntField("FunctionId", FunctionId); Json.UIntField("NodeId", func.GetNodeId()); } - if (AllRelevantMembers) { - if (hasSymbols) - Json.StringField( - "Name", - Reflection - .Strings[Reflection.NodeSymbols[func.GetNodeId()].GetNameId()]); - - else if (IsVerbose) - Json.StringField("Name", ""); - } + if (AllRelevantMembers && hasSymbols) + Json.StringField( + "Name", + Reflection + .Strings[Reflection.NodeSymbols[func.GetNodeId()].GetNameId()]); if (!func.HasDefinition() || AllRelevantMembers) Json.BoolField("HasDefinition", func.HasDefinition()); - if (IsVerbose) { - Json.UIntField("NumParameters", func.GetNumParameters()); - Json.BoolField("HasReturn", func.HasReturn()); - } - - Json.Object("Params", [&Reflection, &func, &Json, hasSymbols, IsVerbose, + Json.Object("Params", [&Reflection, &func, &Json, hasSymbols, AllRelevantMembers, HideFileInfo]() { for (uint32_t i = 0; i < uint32_t(func.GetNumParameters()); ++i) { @@ -906,25 +850,20 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, : std::to_string(i); Json.Object(paramName.c_str(), [&Reflection, &func, &Json, hasSymbols, - IsVerbose, ¶m, &node, - AllRelevantMembers, nodeId, + ¶m, &node, AllRelevantMembers, nodeId, HideFileInfo]() { - if (hasSymbols && !HideFileInfo) { const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[nodeId]; - Json.Object("Symbol", [&Json, &Reflection, &sym, IsVerbose, - AllRelevantMembers, HideFileInfo]() { - PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers, - HideFileInfo, true); + Json.Object("Symbol", [&Json, &Reflection, &sym, AllRelevantMembers, + HideFileInfo]() { + PrintSymbol(Json, Reflection, sym, AllRelevantMembers, HideFileInfo, + true); }); } - else if (IsVerbose) - Json.NullField("Symbol"); - - PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, Json, + PrintParameter(Reflection, param.TypeId, hasSymbols, Json, node.GetSemanticId(), param.InterpolationMode, param.Flags, AllRelevantMembers); }); @@ -932,27 +871,19 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, }); if (!func.HasReturn()) - Json.Object("ReturnType", [&Json, IsVerbose]() { - - Json.StringField("TypeName", "void"); - - if (IsVerbose) { - Json.IntField("TypeId", -1); - Json.Array("ArraySize", []() {}); - Json.StringField("UnderlyingName", "void"); - Json.Array("UnderlyingArraySize", []() {}); - } - }); + Json.Object("ReturnType", + [&Json]() { Json.StringField("TypeName", "void"); }); else { const ReflectionNode &node = Reflection.Nodes[func.GetNodeId() + 1 + func.GetNumParameters()]; - const ReflectionFunctionParameter ¶m = Reflection.Parameters[node.GetLocalId()]; + const ReflectionFunctionParameter ¶m = + Reflection.Parameters[node.GetLocalId()]; - Json.Object("ReturnType", [&Reflection, &func, &Json, hasSymbols, IsVerbose, - ¶m, &node, AllRelevantMembers]() { - PrintParameter(Reflection, param.TypeId, hasSymbols, IsVerbose, Json, + Json.Object("ReturnType", [&Reflection, &func, &Json, hasSymbols, ¶m, + &node, AllRelevantMembers]() { + PrintParameter(Reflection, param.TypeId, hasSymbols, Json, node.GetSemanticId(), param.InterpolationMode, param.Flags, AllRelevantMembers); }); @@ -960,8 +891,8 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, } static void PrintEnumValue(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t NodeId, bool IsVerbose, - bool AllRelevantMembers, bool HideFileInfo) { + uint32_t NodeId, bool AllRelevantMembers, + bool HideFileInfo) { const ReflectionNode &child = Reflection.Nodes[NodeId]; @@ -988,18 +919,16 @@ static void PrintEnumValue(JsonWriter &Json, const ReflectionData &Reflection, const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; - Json.Object("Symbol", [&Json, &Reflection, &sym, IsVerbose, - AllRelevantMembers, HideFileInfo]() { - PrintSymbol(Json, Reflection, sym, IsVerbose, AllRelevantMembers, HideFileInfo, false); - }); + Json.Object("Symbol", + [&Json, &Reflection, &sym, AllRelevantMembers, HideFileInfo]() { + PrintSymbol(Json, Reflection, sym, AllRelevantMembers, + HideFileInfo, false); + }); } - - else if (IsVerbose) - Json.NullField("Symbol"); } static void PrintEnum(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t EnumId, bool IsVerbose, bool AllRelevantMembers, + uint32_t EnumId, bool AllRelevantMembers, bool HideFileInfo) { const ReflectionEnumeration &enm = Reflection.Enums[EnumId]; @@ -1008,7 +937,7 @@ static void PrintEnum(JsonWriter &Json, const ReflectionData &Reflection, bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (AllRelevantMembers || IsVerbose || !hasSymbols) { + if (AllRelevantMembers || !hasSymbols) { Json.UIntField("EnumId", EnumId); Json.UIntField("NodeId", enm.NodeId); } @@ -1018,12 +947,9 @@ static void PrintEnum(JsonWriter &Json, const ReflectionData &Reflection, "Name", Reflection.Strings[Reflection.NodeSymbols[enm.NodeId].GetNameId()]); - else if (IsVerbose) - Json.StringField("Name", ""); - Json.StringField("EnumType", EnumTypeToString(enm.Type)); - Json.Array("Values", [&Json, &node, &enm, hasSymbols, &Reflection, IsVerbose, + Json.Array("Values", [&Json, &node, &enm, hasSymbols, &Reflection, AllRelevantMembers, HideFileInfo]() { for (uint32_t i = 0; i < node.GetChildCount(); ++i) { @@ -1031,10 +957,11 @@ static void PrintEnum(JsonWriter &Json, const ReflectionData &Reflection, JsonWriter::ObjectScope valueRoot(Json); - if (!hasSymbols || AllRelevantMembers || IsVerbose) + if (!hasSymbols || AllRelevantMembers) Json.UIntField("ValueId", i); - PrintEnumValue(Json, Reflection, childId, IsVerbose, AllRelevantMembers, HideFileInfo); + PrintEnumValue(Json, Reflection, childId, AllRelevantMembers, + HideFileInfo); } }); } @@ -1047,37 +974,34 @@ static void PrintAnnotation(JsonWriter &Json, const ReflectionData &Reflection, } static uint32_t PrintBufferMember(const ReflectionData &Reflection, - uint32_t NodeId, uint32_t ChildId, bool HasSymbols, - bool IsVerbose, bool AllRelevantMembers, + uint32_t NodeId, uint32_t ChildId, + bool HasSymbols, bool AllRelevantMembers, JsonWriter &Json) { const ReflectionNode &node = Reflection.Nodes[NodeId]; JsonWriter::ObjectScope root(Json); - if (IsVerbose || AllRelevantMembers) + if (AllRelevantMembers) Json.UIntField("NodeId", NodeId); - if (!HasSymbols || AllRelevantMembers || IsVerbose) + if (!HasSymbols || AllRelevantMembers) Json.UIntField("ChildId", ChildId); if (HasSymbols) Json.StringField( "Name", Reflection.Strings[Reflection.NodeSymbols[NodeId].GetNameId()]); - else if (IsVerbose) - Json.StringField("Name", ""); - - PrintType(Reflection, node.GetLocalId(), HasSymbols, IsVerbose, - AllRelevantMembers, Json, true, "TypeName"); + PrintType(Reflection, node.GetLocalId(), HasSymbols, AllRelevantMembers, Json, + true, "TypeName"); return node.GetChildCount(); } static void PrintBuffer(const ReflectionData &Reflection, uint32_t BufferId, - bool HasSymbols, bool IsVerbose, bool AllRelevantMembers, - JsonWriter &Json) { - + bool HasSymbols, bool AllRelevantMembers, + JsonWriter &Json) { + JsonWriter::ObjectScope nodeRoot(Json); const ReflectionShaderBuffer &buf = Reflection.Buffers[BufferId]; const ReflectionNode &node = Reflection.Nodes[buf.NodeId]; @@ -1085,7 +1009,7 @@ static void PrintBuffer(const ReflectionData &Reflection, uint32_t BufferId, bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (AllRelevantMembers || IsVerbose || !hasSymbols) { + if (AllRelevantMembers || !hasSymbols) { Json.UIntField("BufferId", BufferId); Json.UIntField("NodeId", buf.NodeId); } @@ -1095,23 +1019,19 @@ static void PrintBuffer(const ReflectionData &Reflection, uint32_t BufferId, "Name", Reflection.Strings[Reflection.NodeSymbols[buf.NodeId].GetNameId()]); - else if (IsVerbose) - Json.StringField("Name", ""); - Json.StringField("Type", BufferTypeToString(buf.Type)); - if (node.GetChildCount() || IsVerbose) + if (node.GetChildCount()) Json.Array("Children", [&node, &Reflection, &buf, &Json, HasSymbols, - IsVerbose, AllRelevantMembers]() { + AllRelevantMembers]() { for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) i += PrintBufferMember(Reflection, buf.NodeId + 1 + i, j, HasSymbols, - IsVerbose, AllRelevantMembers, Json); + AllRelevantMembers, Json); }); } static void PrintStatement(const ReflectionData &Reflection, - const ReflectionScopeStmt &Stmt, JsonWriter &Json, - bool IsVerbose) { + const ReflectionScopeStmt &Stmt, JsonWriter &Json) { const ReflectionNode &node = Reflection.Nodes[Stmt.GetNodeId()]; @@ -1122,26 +1042,26 @@ static void PrintStatement(const ReflectionData &Reflection, bool isIf = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF; - if (isIf || IsVerbose) + if (isIf) Json.BoolField("HasElse", Stmt.HasElse()); - if (nodesA || IsVerbose) + if (nodesA) Json.UIntField("NodesA", nodesA); - if (nodesB || IsVerbose) + if (nodesB) Json.UIntField("NodesB", nodesB); } uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, - JsonWriter &Json, bool IsVerbose, + JsonWriter &Json, bool IsHumanFriendly, bool HideFileInfo); void PrintChildren(const ReflectionData &Data, JsonWriter &Json, const char *ObjectName, uint32_t Start, uint32_t End, - bool IsVerbose, bool HideFileInfo, bool IsHumanFriendly) { + bool HideFileInfo, bool IsHumanFriendly) { if (End > Start) - Json.Array(ObjectName, [&Data, &Json, Start, End, IsVerbose, HideFileInfo, + Json.Array(ObjectName, [&Data, &Json, Start, End, HideFileInfo, IsHumanFriendly]() { for (uint32_t i = Start; i < End; ++i) { @@ -1157,24 +1077,21 @@ void PrintChildren(const ReflectionData &Data, JsonWriter &Json, // Put Name(Id) into current scope to hide "Symbol" everywhere. if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) - PrintSymbol(Json, Data, Data.NodeSymbols[i], false, - !IsHumanFriendly, true, false); + PrintSymbol(Json, Data, Data.NodeSymbols[i], !IsHumanFriendly, true, + false); - i += PrintNodeRecursive(Data, i, Json, IsVerbose, true, HideFileInfo); + i += PrintNodeRecursive(Data, i, Json, true, HideFileInfo); } }); } uint32_t PrintNodeRecursive(const ReflectionData &Reflection, - uint32_t NodeId, JsonWriter &Json, bool IsVerbose, + uint32_t NodeId, JsonWriter &Json, bool IsHumanFriendly, bool HideFileInfo) { - bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - // Self - ReflectionNode node = Reflection.Nodes[NodeId]; // In case we're a fwd declare, don't change how we walk the tree @@ -1195,7 +1112,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, node = Reflection.Nodes[NodeId]; } - PrintNode(Json, Reflection, NodeId, IsVerbose, !IsHumanFriendly, + PrintNode(Json, Reflection, NodeId, !IsHumanFriendly, HideFileInfo); uint32_t childrenToSkip = 0; @@ -1203,42 +1120,33 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, // Function if (nodeType == D3D12_HLSL_NODE_TYPE_FUNCTION) - Json.Object("Function", [&node, &Reflection, &Json, IsVerbose, + Json.Object("Function", [&node, &Reflection, &Json, IsHumanFriendly, &childrenToSkip, HideFileInfo]() { ReflectionFunction func = Reflection.Functions[node.GetLocalId()]; - PrintFunction(Json, Reflection, node.GetLocalId(), IsVerbose, + PrintFunction(Json, Reflection, node.GetLocalId(), !IsHumanFriendly, HideFileInfo); childrenToSkip = func.GetNumParameters() + func.HasReturn(); }); - else if (IsVerbose) - Json.NullField("Function"); - // Register if (nodeType == D3D12_HLSL_NODE_TYPE_REGISTER) Json.Object("Register", - [&node, &Reflection, &Json, IsVerbose, IsHumanFriendly]() { - PrintRegister(Json, Reflection, node.GetLocalId(), IsVerbose, + [&node, &Reflection, &Json, IsHumanFriendly]() { + PrintRegister(Json, Reflection, node.GetLocalId(), !IsHumanFriendly); }); - else if (IsVerbose) - Json.NullField("Register"); - // Enum if (nodeType == D3D12_HLSL_NODE_TYPE_ENUM) - Json.Object("Enum", [&node, &Reflection, &Json, IsVerbose, IsHumanFriendly, + Json.Object("Enum", [&node, &Reflection, &Json, IsHumanFriendly, &childrenToSkip, HideFileInfo]() { - PrintEnum(Json, Reflection, node.GetLocalId(), IsVerbose, + PrintEnum(Json, Reflection, node.GetLocalId(), !IsHumanFriendly, HideFileInfo); childrenToSkip = node.GetChildCount(); }); - else if (IsVerbose) - Json.NullField("Enum"); - // Type bool isType = false; @@ -1258,15 +1166,12 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, } if (isType) - Json.Object("Type", [&node, &Reflection, &Json, IsVerbose, IsHumanFriendly, + Json.Object("Type", [&node, &Reflection, &Json, IsHumanFriendly, hasSymbols, recurseType]() { - PrintType(Reflection, node.GetLocalId(), hasSymbols, IsVerbose, + PrintType(Reflection, node.GetLocalId(), hasSymbols, !IsHumanFriendly, Json, recurseType); }); - else if (IsVerbose) - Json.NullField("Type"); - // If; turns into ("Condition"), ("Body"), ("Else") // While; turns into ("Condition"), ("Body") // For; turns into ("Condition"), ("Init"), ("Body") @@ -1295,22 +1200,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, if (stmtType) { - if (IsVerbose) { - - if (nodeType != D3D12_HLSL_NODE_TYPE_IF) - Json.NullField("If"); - - if (nodeType != D3D12_HLSL_NODE_TYPE_WHILE) - Json.NullField("While"); - - if (nodeType != D3D12_HLSL_NODE_TYPE_SWITCH) - Json.NullField("Switch"); - - if (nodeType != D3D12_HLSL_NODE_TYPE_FOR) - Json.NullField("For"); - } - - Json.Object(stmtType, [&node, &Reflection, &Json, IsVerbose, + Json.Object(stmtType, [&node, &Reflection, &Json, IsHumanFriendly, NodeId, &childrenToSkip, nodeType, HideFileInfo]() { const ReflectionScopeStmt &stmt = Reflection.Statements[node.GetLocalId()]; @@ -1318,28 +1208,22 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t start = NodeId + 1; if (stmt.HasConditionVar()) - Json.Object("Condition", [NodeId, &Reflection, &Json, IsVerbose, + Json.Object("Condition", [NodeId, &Reflection, &Json, IsHumanFriendly, &start, HideFileInfo]() { - start += PrintNodeRecursive(Reflection, start, Json, IsVerbose, + start += PrintNodeRecursive(Reflection, start, Json, IsHumanFriendly, HideFileInfo); ++start; }); - else if (IsVerbose) - Json.NullField("Condition"); - uint32_t end = start + stmt.GetNodeCount(); bool isIf = nodeType == D3D12_HLSL_NODE_TYPE_IF; const char *bodyName = isIf ? "Body" : "Init"; if (stmt.GetNodeCount()) - PrintChildren(Reflection, Json, bodyName, start, end, IsVerbose, + PrintChildren(Reflection, Json, bodyName, start, end, HideFileInfo, IsHumanFriendly); - else if (IsVerbose) - Json.NullField(bodyName); - const char *elseName = isIf ? "Else" : "Body"; if (stmt.HasElse() || !isIf) { @@ -1347,30 +1231,20 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, start = end; end = NodeId + 1 + node.GetChildCount(); - PrintChildren(Reflection, Json, elseName, start, end, IsVerbose, + PrintChildren(Reflection, Json, elseName, start, end, HideFileInfo, IsHumanFriendly); } - else if (IsVerbose) - Json.NullField(elseName); - childrenToSkip = node.GetChildCount(); }); } - else if (IsVerbose) { - Json.NullField("If"); - Json.NullField("While"); - Json.NullField("Switch"); - Json.NullField("For"); - } - // Children uint32_t start = NodeId + 1 + childrenToSkip; uint32_t end = NodeId + 1 + node.GetChildCount(); - PrintChildren(Reflection, Json, "Children", start, end, IsVerbose, + PrintChildren(Reflection, Json, "Children", start, end, HideFileInfo, IsHumanFriendly); return nodeChildCountForRet; @@ -1378,8 +1252,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, // IsHumanFriendly = false: Raw view of the real file data // IsHumanFriendly = true: Clean view that's relatively close to the real tree -std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly, - bool IsVerbose) const { +std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) const { JsonWriter json; @@ -1417,24 +1290,24 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly, json.Value(uint64_t(id)); }); - json.Array("Nodes", [this, &json, IsVerbose, HideFileInfo] { + json.Array("Nodes", [this, &json, HideFileInfo] { for (uint32_t i = 0; i < uint32_t(Nodes.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintNode(json, *this, i, IsVerbose, true, HideFileInfo); + PrintNode(json, *this, i, true, HideFileInfo); } }); - json.Array("Registers", [this, &json, IsVerbose] { + json.Array("Registers", [this, &json] { for (uint32_t i = 0; i < uint32_t(Registers.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintRegister(json, *this, i, IsVerbose, true); + PrintRegister(json, *this, i, true); } }); - json.Array("Functions", [this, &json, IsVerbose, HideFileInfo] { + json.Array("Functions", [this, &json, HideFileInfo] { for (uint32_t i = 0; i < uint32_t(Functions.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintFunction(json, *this, i, IsVerbose, true, HideFileInfo); + PrintFunction(json, *this, i, true, HideFileInfo); } }); @@ -1442,7 +1315,7 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly, // before, still printing it to allow consistency checks. // For pure pretty prints, you should use the human version. - json.Array("Parameters", [this, &json, hasSymbols, IsVerbose] { + json.Array("Parameters", [this, &json, hasSymbols] { for (uint32_t i = 0; i < uint32_t(Parameters.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); @@ -1453,24 +1326,24 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly, json.StringField("ParamName", paramName); - PrintParameter(*this, param.TypeId, hasSymbols, IsVerbose, json, + PrintParameter(*this, param.TypeId, hasSymbols, json, Nodes[param.NodeId].GetSemanticId(), param.InterpolationMode, param.Flags, true); } }); - json.Array("Enums", [this, &json, hasSymbols, IsVerbose, HideFileInfo] { + json.Array("Enums", [this, &json, hasSymbols, HideFileInfo] { for (uint32_t i = 0; i < uint32_t(Enums.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintEnum(json, *this, i, IsVerbose, true, HideFileInfo); + PrintEnum(json, *this, i, true, HideFileInfo); } }); - json.Array("EnumValues", [this, &json, hasSymbols, IsVerbose, + json.Array("EnumValues", [this, &json, hasSymbols, HideFileInfo] { for (uint32_t i = 0; i < uint32_t(EnumValues.size()); ++i) { JsonWriter::ObjectScope valueRoot(json); - PrintEnumValue(json, *this, EnumValues[i].NodeId, IsVerbose, true, + PrintEnumValue(json, *this, EnumValues[i].NodeId, true, HideFileInfo); } }); @@ -1503,7 +1376,7 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly, json.Value(uint64_t(id)); }); - json.Array("Members", [this, &json, hasSymbols, IsVerbose] { + json.Array("Members", [this, &json, hasSymbols] { for (uint32_t i = 0; i < uint32_t(MemberTypeIds.size()); ++i) { JsonWriter::ObjectScope valueRoot(json); @@ -1513,31 +1386,31 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly, json.UIntField("NameId", MemberNameIds[i]); } - PrintTypeName(*this, MemberTypeIds[i], hasSymbols, IsVerbose, true, + PrintTypeName(*this, MemberTypeIds[i], hasSymbols, true, json, "TypeName"); } }); - json.Array("TypeList", [this, &json, hasSymbols, IsVerbose] { + json.Array("TypeList", [this, &json, hasSymbols] { for (uint32_t id : TypeList) { JsonWriter::ObjectScope valueRoot(json); - PrintTypeName(*this, id, hasSymbols, IsVerbose, true, json); + PrintTypeName(*this, id, hasSymbols, true, json); } }); - json.Array("Types", [this, &json, hasSymbols, IsVerbose] { + json.Array("Types", [this, &json, hasSymbols] { for (uint32_t i = 0; i < uint32_t(Types.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintType(*this, i, hasSymbols, IsVerbose, true, json, false); + PrintType(*this, i, hasSymbols, true, json, false); } }); - json.Array("Buffers", [this, &json, hasSymbols, IsVerbose] { + json.Array("Buffers", [this, &json, hasSymbols] { for (uint32_t i = 0; i < uint32_t(Buffers.size()); ++i) - PrintBuffer(*this, i, hasSymbols, IsVerbose, true, json); + PrintBuffer(*this, i, hasSymbols, true, json); }); - json.Array("Statements", [this, &json, IsVerbose] { + json.Array("Statements", [this, &json] { for (uint32_t i = 0; i < uint32_t(Statements.size()); ++i) { const ReflectionScopeStmt &stat = Statements[i]; @@ -1547,13 +1420,13 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly, Nodes[stat.GetNodeId()].GetNodeType())); json.UIntField("NodeId", stat.GetNodeId()); - PrintStatement(*this, stat, json, IsVerbose); + PrintStatement(*this, stat, json); } }); } else - PrintChildren(*this, json, "Children", 1, Nodes.size(), IsVerbose, + PrintChildren(*this, json, "Children", 1, Nodes.size(), HideFileInfo, true); } From 436c88edc469e2b54ace3a6eb31e790d43a9d76a Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 11 Nov 2025 00:10:58 +0100 Subject: [PATCH 100/126] Replaced AllRelevantMembers and HideFileInfo with ReflectionPrintSettings for clarity --- .../DxcReflectionJson.cpp | 299 +++++++++--------- 1 file changed, 145 insertions(+), 154 deletions(-) diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 62217b1676..115fd49ff0 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -470,21 +470,26 @@ static void FillArraySizes(const ReflectionData &Reflection, Array.push_back(Reflection.ArraySizes[arr.ArrayStart() + i]); } +struct ReflectionPrintSettings { + bool HumanReadable; + bool HideFileInfo; +}; + static void PrintSymbol(JsonWriter &Json, const ReflectionData &Reflection, const ReflectionNodeSymbol &Sym, - bool AllRelevantMembers, bool HideFileInfo, + const ReflectionPrintSettings &Settings, bool MuteName) { if (Sym.GetNameId() && !MuteName) { Json.StringField("Name", Reflection.Strings[Sym.GetNameId()]); - if (AllRelevantMembers) + if (!Settings.HumanReadable) Json.UIntField("NameId", Sym.GetNameId()); } - if (HideFileInfo) + if (Settings.HideFileInfo) return; if (Sym.HasFileSource()) { @@ -493,7 +498,7 @@ static void PrintSymbol(JsonWriter &Json, "Source", Reflection.Strings[Reflection.Sources[Sym.GetFileSourceId()]]); - if (AllRelevantMembers) + if (!Settings.HumanReadable) Json.UIntField("SourceId", Sym.GetFileSourceId()); Json.UIntField("LineId", Sym.GetSourceLineStart()); @@ -510,20 +515,20 @@ static void PrintSymbol(JsonWriter &Json, // Verbose will still print fields even if they aren't relevant, // while all members will not silence important info but that might not matter for human readability static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t NodeId, bool AllRelevantMembers, - bool HideFileInfo) { + uint32_t NodeId, + const ReflectionPrintSettings &Settings) { const ReflectionNode &node = Reflection.Nodes[NodeId]; bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (AllRelevantMembers || !hasSymbols) + if (!Settings.HumanReadable || !hasSymbols) Json.UIntField("NodeId", NodeId); Json.StringField("NodeType", NodeTypeToString(node.GetNodeType())); - if (AllRelevantMembers) { + if (!Settings.HumanReadable) { Json.UIntField("NodeTypeId", node.GetNodeType()); Json.UIntField("LocalId", node.GetLocalId()); Json.IntField("ParentId", node.GetParentId() == uint16_t(-1) @@ -531,7 +536,7 @@ static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, : int64_t(node.GetParentId())); } - if (node.GetChildCount() && AllRelevantMembers) { + if (node.GetChildCount() && !Settings.HumanReadable) { Json.UIntField("ChildCount", node.GetChildCount()); Json.UIntField("ChildStart", NodeId + 1); } @@ -541,13 +546,13 @@ static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, Json.StringField("Semantic", Reflection.StringsNonDebug[node.GetSemanticId()]); - if (AllRelevantMembers) + if (!Settings.HumanReadable) Json.UIntField("SemanticId", node.GetSemanticId()); } if (node.GetAnnotationCount()) { - if (AllRelevantMembers) { + if (!Settings.HumanReadable) { Json.UIntField("AnnotationStart", node.GetAnnotationStart()); Json.UIntField("AnnotationCount", node.GetAnnotationCount()); } @@ -571,35 +576,35 @@ static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, }); } - if ((node.IsFwdBckDefined() || node.IsFwdDeclare()) && AllRelevantMembers) { + if ((node.IsFwdBckDefined() || node.IsFwdDeclare()) && + !Settings.HumanReadable) { Json.BoolField("IsFwdDeclare", node.IsFwdDeclare()); Json.IntField("FwdBack", !node.IsFwdBckDefined() ? -1 : int64_t(node.GetFwdBck())); } - if (hasSymbols && !HideFileInfo) - Json.Object("Symbol", [&Reflection, &Json, NodeId, - AllRelevantMembers, HideFileInfo] { + if (hasSymbols && !Settings.HideFileInfo) + Json.Object("Symbol", [&Reflection, &Json, NodeId, &Settings] { const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; - PrintSymbol(Json, Reflection, sym, AllRelevantMembers, - HideFileInfo, true); + PrintSymbol(Json, Reflection, sym, Settings, true); }); } static void PrintRegister(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t RegisterId, bool AllRelevantMembers) { + uint32_t RegisterId, + const ReflectionPrintSettings &Settings) { const ReflectionShaderResource ® = Reflection.Registers[RegisterId]; bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (AllRelevantMembers || !hasSymbols) { + if (!Settings.HumanReadable || !hasSymbols) { Json.UIntField("RegisterId", RegisterId); Json.UIntField("NodeId", reg.GetNodeId()); } - if (AllRelevantMembers && hasSymbols) + if (!Settings.HumanReadable && hasSymbols) Json.StringField( "Name", Reflection @@ -618,7 +623,7 @@ static void PrintRegister(JsonWriter &Json, const ReflectionData &Reflection, if (reg.GetArrayId() != uint32_t(-1)) { - if (AllRelevantMembers) + if (!Settings.HumanReadable) Json.UIntField("ArrayId", reg.GetArrayId()); Json.Array("ArraySize", [&Reflection, ®, &Json]() { @@ -643,7 +648,7 @@ static void PrintRegister(JsonWriter &Json, const ReflectionData &Reflection, break; } - if (printBufferId && AllRelevantMembers) + if (printBufferId && !Settings.HumanReadable) Json.UIntField("BufferId", reg.GetBufferId()); if (reg.GetFlags()) @@ -668,11 +673,12 @@ static void PrintRegister(JsonWriter &Json, const ReflectionData &Reflection, } static void PrintTypeName(const ReflectionData &Reflection, uint32_t TypeId, - bool HasSymbols, bool AllRelevantMembers, + bool HasSymbols, + const ReflectionPrintSettings &Settings, JsonWriter &Json, const char *NameForTypeName = "Name") { - if (AllRelevantMembers || !HasSymbols) + if (!Settings.HumanReadable || !HasSymbols) Json.UIntField("TypeId", TypeId); std::string name; @@ -716,41 +722,41 @@ static void PrintTypeName(const ReflectionData &Reflection, uint32_t TypeId, } static void PrintType(const ReflectionData &Reflection, uint32_t TypeId, - bool HasSymbols, bool AllRelevantMembers, + bool HasSymbols, const ReflectionPrintSettings &Settings, JsonWriter &Json, bool Recursive, const char *NameForTypeName = "Name") { const ReflectionVariableType &type = Reflection.Types[TypeId]; - PrintTypeName(Reflection, TypeId, HasSymbols, AllRelevantMembers, Json, + PrintTypeName(Reflection, TypeId, HasSymbols, Settings, Json, NameForTypeName); if (type.GetBaseClass() != uint32_t(-1)) - Json.Object("BaseClass", [&Reflection, &Json, &type, HasSymbols, - AllRelevantMembers, Recursive]() { + Json.Object("BaseClass", [&Reflection, &Json, &type, HasSymbols, Settings, + Recursive]() { if (Recursive) - PrintType(Reflection, type.GetBaseClass(), HasSymbols, - AllRelevantMembers, Json, true, "TypeName"); + PrintType(Reflection, type.GetBaseClass(), HasSymbols, Settings, Json, + true, "TypeName"); else - PrintTypeName(Reflection, type.GetBaseClass(), HasSymbols, - AllRelevantMembers, Json, "TypeName"); + PrintTypeName(Reflection, type.GetBaseClass(), HasSymbols, Settings, + Json, "TypeName"); }); if (type.GetInterfaceCount()) Json.Array("Interfaces", [&Reflection, &Json, &type, HasSymbols, - AllRelevantMembers]() { + Settings]() { for (uint32_t i = 0; i < uint32_t(type.GetInterfaceCount()); ++i) { uint32_t interfaceId = type.GetInterfaceStart() + i; JsonWriter::ObjectScope nodeRoot(Json); PrintTypeName(Reflection, Reflection.TypeList[interfaceId], HasSymbols, - AllRelevantMembers, Json); + Settings, Json); } }); if (type.GetMemberCount()) - Json.Array("Members", [&Reflection, &Json, &type, HasSymbols, - AllRelevantMembers, Recursive]() { + Json.Array("Members", [&Reflection, &Json, &type, HasSymbols, Settings, + Recursive]() { for (uint32_t i = 0; i < uint32_t(type.GetMemberCount()); ++i) { uint32_t memberId = type.GetMemberStart() + i; @@ -760,17 +766,17 @@ static void PrintType(const ReflectionData &Reflection, uint32_t TypeId, Json.StringField( "Name", Reflection.Strings[Reflection.MemberNameIds[memberId]]); - if (AllRelevantMembers) + if (!Settings.HumanReadable) Json.UIntField("NameId", Reflection.MemberNameIds[memberId]); } if (Recursive) PrintType(Reflection, Reflection.MemberTypeIds[memberId], HasSymbols, - AllRelevantMembers, Json, true, "TypeName"); + Settings, Json, true, "TypeName"); else PrintTypeName(Reflection, Reflection.MemberTypeIds[memberId], - HasSymbols, AllRelevantMembers, Json, "TypeName"); + HasSymbols, Settings, Json, "TypeName"); } }); } @@ -778,15 +784,16 @@ static void PrintType(const ReflectionData &Reflection, uint32_t TypeId, static void PrintParameter(const ReflectionData &Reflection, uint32_t TypeId, bool HasSymbols, JsonWriter &Json, uint32_t SemanticId, uint8_t InterpolationMode, - uint8_t Flags, bool AllRelevantMembers) { + uint8_t Flags, + const ReflectionPrintSettings &Settings) { - PrintTypeName(Reflection, TypeId, HasSymbols, AllRelevantMembers, Json, "TypeName"); + PrintTypeName(Reflection, TypeId, HasSymbols, Settings, Json, "TypeName"); if (SemanticId != uint32_t(-1)) { Json.StringField("Semantic", Reflection.StringsNonDebug[SemanticId]); - if (AllRelevantMembers) + if (!Settings.HumanReadable) Json.UIntField("SemanticId", SemanticId); } @@ -813,30 +820,29 @@ static void PrintParameter(const ReflectionData &Reflection, uint32_t TypeId, } static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t FunctionId, bool AllRelevantMembers, - bool HideFileInfo) { + uint32_t FunctionId, + const ReflectionPrintSettings &Settings) { const ReflectionFunction &func = Reflection.Functions[FunctionId]; bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (AllRelevantMembers || !hasSymbols) { + if (!Settings.HumanReadable || !hasSymbols) { Json.UIntField("FunctionId", FunctionId); Json.UIntField("NodeId", func.GetNodeId()); } - if (AllRelevantMembers && hasSymbols) + if (!Settings.HumanReadable && hasSymbols) Json.StringField( "Name", Reflection .Strings[Reflection.NodeSymbols[func.GetNodeId()].GetNameId()]); - if (!func.HasDefinition() || AllRelevantMembers) + if (!func.HasDefinition() || !Settings.HumanReadable) Json.BoolField("HasDefinition", func.HasDefinition()); - Json.Object("Params", [&Reflection, &func, &Json, hasSymbols, - AllRelevantMembers, HideFileInfo]() { + Json.Object("Params", [&Reflection, &func, &Json, hasSymbols, &Settings]() { for (uint32_t i = 0; i < uint32_t(func.GetNumParameters()); ++i) { uint32_t nodeId = func.GetNodeId() + 1 + i; @@ -850,22 +856,19 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, : std::to_string(i); Json.Object(paramName.c_str(), [&Reflection, &func, &Json, hasSymbols, - ¶m, &node, AllRelevantMembers, nodeId, - HideFileInfo]() { - if (hasSymbols && !HideFileInfo) { + ¶m, &node, &Settings, nodeId]() { + if (hasSymbols && !Settings.HideFileInfo) { const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[nodeId]; - Json.Object("Symbol", [&Json, &Reflection, &sym, AllRelevantMembers, - HideFileInfo]() { - PrintSymbol(Json, Reflection, sym, AllRelevantMembers, HideFileInfo, - true); + Json.Object("Symbol", [&Json, &Reflection, &sym, &Settings]() { + PrintSymbol(Json, Reflection, sym, Settings, true); }); } PrintParameter(Reflection, param.TypeId, hasSymbols, Json, node.GetSemanticId(), param.InterpolationMode, - param.Flags, AllRelevantMembers); + param.Flags, Settings); }); } }); @@ -882,17 +885,17 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, Reflection.Parameters[node.GetLocalId()]; Json.Object("ReturnType", [&Reflection, &func, &Json, hasSymbols, ¶m, - &node, AllRelevantMembers]() { + &node, &Settings]() { PrintParameter(Reflection, param.TypeId, hasSymbols, Json, node.GetSemanticId(), param.InterpolationMode, param.Flags, - AllRelevantMembers); + Settings); }); } } static void PrintEnumValue(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t NodeId, bool AllRelevantMembers, - bool HideFileInfo) { + uint32_t NodeId, + const ReflectionPrintSettings &Settings) { const ReflectionNode &child = Reflection.Nodes[NodeId]; @@ -919,17 +922,15 @@ static void PrintEnumValue(JsonWriter &Json, const ReflectionData &Reflection, const ReflectionNodeSymbol &sym = Reflection.NodeSymbols[NodeId]; - Json.Object("Symbol", - [&Json, &Reflection, &sym, AllRelevantMembers, HideFileInfo]() { - PrintSymbol(Json, Reflection, sym, AllRelevantMembers, - HideFileInfo, false); - }); + Json.Object("Symbol", [&Json, &Reflection, &sym, &Settings]() { + PrintSymbol(Json, Reflection, sym, Settings, false); + }); } } static void PrintEnum(JsonWriter &Json, const ReflectionData &Reflection, - uint32_t EnumId, bool AllRelevantMembers, - bool HideFileInfo) { + uint32_t EnumId, + const ReflectionPrintSettings &Settings) { const ReflectionEnumeration &enm = Reflection.Enums[EnumId]; const ReflectionNode &node = Reflection.Nodes[enm.NodeId]; @@ -937,7 +938,7 @@ static void PrintEnum(JsonWriter &Json, const ReflectionData &Reflection, bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (AllRelevantMembers || !hasSymbols) { + if (!Settings.HumanReadable || !hasSymbols) { Json.UIntField("EnumId", EnumId); Json.UIntField("NodeId", enm.NodeId); } @@ -949,21 +950,20 @@ static void PrintEnum(JsonWriter &Json, const ReflectionData &Reflection, Json.StringField("EnumType", EnumTypeToString(enm.Type)); - Json.Array("Values", [&Json, &node, &enm, hasSymbols, &Reflection, - AllRelevantMembers, HideFileInfo]() { - for (uint32_t i = 0; i < node.GetChildCount(); ++i) { + Json.Array("Values", + [&Json, &node, &enm, hasSymbols, &Reflection, &Settings]() { + for (uint32_t i = 0; i < node.GetChildCount(); ++i) { - uint32_t childId = enm.NodeId + 1 + i; + uint32_t childId = enm.NodeId + 1 + i; - JsonWriter::ObjectScope valueRoot(Json); + JsonWriter::ObjectScope valueRoot(Json); - if (!hasSymbols || AllRelevantMembers) - Json.UIntField("ValueId", i); + if (!hasSymbols || !Settings.HumanReadable) + Json.UIntField("ValueId", i); - PrintEnumValue(Json, Reflection, childId, AllRelevantMembers, - HideFileInfo); - } - }); + PrintEnumValue(Json, Reflection, childId, Settings); + } + }); } static void PrintAnnotation(JsonWriter &Json, const ReflectionData &Reflection, @@ -975,31 +975,33 @@ static void PrintAnnotation(JsonWriter &Json, const ReflectionData &Reflection, static uint32_t PrintBufferMember(const ReflectionData &Reflection, uint32_t NodeId, uint32_t ChildId, - bool HasSymbols, bool AllRelevantMembers, + bool HasSymbols, + const ReflectionPrintSettings &Settings, JsonWriter &Json) { const ReflectionNode &node = Reflection.Nodes[NodeId]; JsonWriter::ObjectScope root(Json); - if (AllRelevantMembers) + if (!Settings.HumanReadable) Json.UIntField("NodeId", NodeId); - if (!HasSymbols || AllRelevantMembers) + if (!HasSymbols || !Settings.HumanReadable) Json.UIntField("ChildId", ChildId); if (HasSymbols) Json.StringField( "Name", Reflection.Strings[Reflection.NodeSymbols[NodeId].GetNameId()]); - PrintType(Reflection, node.GetLocalId(), HasSymbols, AllRelevantMembers, Json, + PrintType(Reflection, node.GetLocalId(), HasSymbols, Settings, Json, true, "TypeName"); return node.GetChildCount(); } static void PrintBuffer(const ReflectionData &Reflection, uint32_t BufferId, - bool HasSymbols, bool AllRelevantMembers, + bool HasSymbols, + const ReflectionPrintSettings &Settings, JsonWriter &Json) { JsonWriter::ObjectScope nodeRoot(Json); @@ -1009,7 +1011,7 @@ static void PrintBuffer(const ReflectionData &Reflection, uint32_t BufferId, bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - if (AllRelevantMembers || !hasSymbols) { + if (!Settings.HumanReadable || !hasSymbols) { Json.UIntField("BufferId", BufferId); Json.UIntField("NodeId", buf.NodeId); } @@ -1022,12 +1024,12 @@ static void PrintBuffer(const ReflectionData &Reflection, uint32_t BufferId, Json.StringField("Type", BufferTypeToString(buf.Type)); if (node.GetChildCount()) - Json.Array("Children", [&node, &Reflection, &buf, &Json, HasSymbols, - AllRelevantMembers]() { - for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) - i += PrintBufferMember(Reflection, buf.NodeId + 1 + i, j, HasSymbols, - AllRelevantMembers, Json); - }); + Json.Array("Children", + [&node, &Reflection, &buf, &Json, HasSymbols, &Settings]() { + for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) + i += PrintBufferMember(Reflection, buf.NodeId + 1 + i, j, + HasSymbols, Settings, Json); + }); } static void PrintStatement(const ReflectionData &Reflection, @@ -1054,15 +1056,14 @@ static void PrintStatement(const ReflectionData &Reflection, uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, JsonWriter &Json, - bool IsHumanFriendly, bool HideFileInfo); + const ReflectionPrintSettings &Settings); void PrintChildren(const ReflectionData &Data, JsonWriter &Json, const char *ObjectName, uint32_t Start, uint32_t End, - bool HideFileInfo, bool IsHumanFriendly) { + const ReflectionPrintSettings &Settings) { if (End > Start) - Json.Array(ObjectName, [&Data, &Json, Start, End, HideFileInfo, - IsHumanFriendly]() { + Json.Array(ObjectName, [&Data, &Json, Start, End, &Settings]() { for (uint32_t i = Start; i < End; ++i) { const ReflectionNode &node = Data.Nodes[i]; @@ -1077,17 +1078,16 @@ void PrintChildren(const ReflectionData &Data, JsonWriter &Json, // Put Name(Id) into current scope to hide "Symbol" everywhere. if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) - PrintSymbol(Json, Data, Data.NodeSymbols[i], !IsHumanFriendly, true, - false); + PrintSymbol(Json, Data, Data.NodeSymbols[i], Settings, false); - i += PrintNodeRecursive(Data, i, Json, true, HideFileInfo); + i += PrintNodeRecursive(Data, i, Json, Settings); } }); } -uint32_t PrintNodeRecursive(const ReflectionData &Reflection, - uint32_t NodeId, JsonWriter &Json, - bool IsHumanFriendly, bool HideFileInfo) { +uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, + JsonWriter &Json, + const ReflectionPrintSettings &Settings) { bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -1112,8 +1112,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, node = Reflection.Nodes[NodeId]; } - PrintNode(Json, Reflection, NodeId, !IsHumanFriendly, - HideFileInfo); + PrintNode(Json, Reflection, NodeId, Settings); uint32_t childrenToSkip = 0; @@ -1121,29 +1120,25 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, if (nodeType == D3D12_HLSL_NODE_TYPE_FUNCTION) Json.Object("Function", [&node, &Reflection, &Json, - IsHumanFriendly, &childrenToSkip, HideFileInfo]() { + &Settings, &childrenToSkip]() { ReflectionFunction func = Reflection.Functions[node.GetLocalId()]; - PrintFunction(Json, Reflection, node.GetLocalId(), - !IsHumanFriendly, HideFileInfo); + PrintFunction(Json, Reflection, node.GetLocalId(), Settings); childrenToSkip = func.GetNumParameters() + func.HasReturn(); }); // Register if (nodeType == D3D12_HLSL_NODE_TYPE_REGISTER) - Json.Object("Register", - [&node, &Reflection, &Json, IsHumanFriendly]() { - PrintRegister(Json, Reflection, node.GetLocalId(), - !IsHumanFriendly); + Json.Object("Register", [&node, &Reflection, &Json, &Settings]() { + PrintRegister(Json, Reflection, node.GetLocalId(), Settings); }); // Enum if (nodeType == D3D12_HLSL_NODE_TYPE_ENUM) - Json.Object("Enum", [&node, &Reflection, &Json, IsHumanFriendly, - &childrenToSkip, HideFileInfo]() { - PrintEnum(Json, Reflection, node.GetLocalId(), - !IsHumanFriendly, HideFileInfo); + Json.Object("Enum", [&node, &Reflection, &Json, &Settings, + &childrenToSkip]() { + PrintEnum(Json, Reflection, node.GetLocalId(), Settings); childrenToSkip = node.GetChildCount(); }); @@ -1166,10 +1161,10 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, } if (isType) - Json.Object("Type", [&node, &Reflection, &Json, IsHumanFriendly, + Json.Object("Type", [&node, &Reflection, &Json, &Settings, hasSymbols, recurseType]() { - PrintType(Reflection, node.GetLocalId(), hasSymbols, - !IsHumanFriendly, Json, recurseType); + PrintType(Reflection, node.GetLocalId(), hasSymbols, Settings, Json, + recurseType); }); // If; turns into ("Condition"), ("Body"), ("Else") @@ -1200,18 +1195,15 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, if (stmtType) { - Json.Object(stmtType, [&node, &Reflection, &Json, - IsHumanFriendly, NodeId, &childrenToSkip, nodeType, - HideFileInfo]() { + Json.Object(stmtType, [&node, &Reflection, &Json, &Settings, NodeId, + &childrenToSkip, nodeType]() { const ReflectionScopeStmt &stmt = Reflection.Statements[node.GetLocalId()]; uint32_t start = NodeId + 1; if (stmt.HasConditionVar()) - Json.Object("Condition", [NodeId, &Reflection, &Json, - IsHumanFriendly, &start, HideFileInfo]() { - start += PrintNodeRecursive(Reflection, start, Json, - IsHumanFriendly, HideFileInfo); + Json.Object("Condition", [NodeId, &Reflection, &Json, &start, &Settings]() { + start += PrintNodeRecursive(Reflection, start, Json, Settings); ++start; }); @@ -1221,8 +1213,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, const char *bodyName = isIf ? "Body" : "Init"; if (stmt.GetNodeCount()) - PrintChildren(Reflection, Json, bodyName, start, end, - HideFileInfo, IsHumanFriendly); + PrintChildren(Reflection, Json, bodyName, start, end, Settings); const char *elseName = isIf ? "Else" : "Body"; @@ -1231,8 +1222,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, start = end; end = NodeId + 1 + node.GetChildCount(); - PrintChildren(Reflection, Json, elseName, start, end, - HideFileInfo, IsHumanFriendly); + PrintChildren(Reflection, Json, elseName, start, end, Settings); } childrenToSkip = node.GetChildCount(); @@ -1244,8 +1234,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t start = NodeId + 1 + childrenToSkip; uint32_t end = NodeId + 1 + node.GetChildCount(); - PrintChildren(Reflection, Json, "Children", start, end, - HideFileInfo, IsHumanFriendly); + PrintChildren(Reflection, Json, "Children", start, end, Settings); return nodeChildCountForRet; } @@ -1266,6 +1255,10 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons bool hasSymbols = Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + ReflectionPrintSettings settings{}; + settings.HideFileInfo = HideFileInfo; + settings.HumanReadable = IsHumanFriendly; + // Print raw contents if (!IsHumanFriendly) { @@ -1290,24 +1283,24 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons json.Value(uint64_t(id)); }); - json.Array("Nodes", [this, &json, HideFileInfo] { + json.Array("Nodes", [this, &json, &settings] { for (uint32_t i = 0; i < uint32_t(Nodes.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintNode(json, *this, i, true, HideFileInfo); + PrintNode(json, *this, i, settings); } }); - json.Array("Registers", [this, &json] { + json.Array("Registers", [this, &json, &settings] { for (uint32_t i = 0; i < uint32_t(Registers.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintRegister(json, *this, i, true); + PrintRegister(json, *this, i, settings); } }); - json.Array("Functions", [this, &json, HideFileInfo] { + json.Array("Functions", [this, &json, HideFileInfo, &settings] { for (uint32_t i = 0; i < uint32_t(Functions.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintFunction(json, *this, i, true, HideFileInfo); + PrintFunction(json, *this, i, settings); } }); @@ -1315,7 +1308,7 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons // before, still printing it to allow consistency checks. // For pure pretty prints, you should use the human version. - json.Array("Parameters", [this, &json, hasSymbols] { + json.Array("Parameters", [this, &json, hasSymbols, &settings] { for (uint32_t i = 0; i < uint32_t(Parameters.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); @@ -1328,23 +1321,21 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons PrintParameter(*this, param.TypeId, hasSymbols, json, Nodes[param.NodeId].GetSemanticId(), - param.InterpolationMode, param.Flags, true); + param.InterpolationMode, param.Flags, settings); } }); - json.Array("Enums", [this, &json, hasSymbols, HideFileInfo] { + json.Array("Enums", [this, &json, hasSymbols, HideFileInfo, &settings] { for (uint32_t i = 0; i < uint32_t(Enums.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintEnum(json, *this, i, true, HideFileInfo); + PrintEnum(json, *this, i, settings); } }); - json.Array("EnumValues", [this, &json, hasSymbols, - HideFileInfo] { + json.Array("EnumValues", [this, &json, hasSymbols, HideFileInfo, &settings] { for (uint32_t i = 0; i < uint32_t(EnumValues.size()); ++i) { JsonWriter::ObjectScope valueRoot(json); - PrintEnumValue(json, *this, EnumValues[i].NodeId, true, - HideFileInfo); + PrintEnumValue(json, *this, EnumValues[i].NodeId, settings); } }); @@ -1376,7 +1367,7 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons json.Value(uint64_t(id)); }); - json.Array("Members", [this, &json, hasSymbols] { + json.Array("Members", [this, &json, hasSymbols, &settings] { for (uint32_t i = 0; i < uint32_t(MemberTypeIds.size()); ++i) { JsonWriter::ObjectScope valueRoot(json); @@ -1386,28 +1377,28 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons json.UIntField("NameId", MemberNameIds[i]); } - PrintTypeName(*this, MemberTypeIds[i], hasSymbols, true, + PrintTypeName(*this, MemberTypeIds[i], hasSymbols, settings, json, "TypeName"); } }); - json.Array("TypeList", [this, &json, hasSymbols] { + json.Array("TypeList", [this, &json, hasSymbols, &settings] { for (uint32_t id : TypeList) { JsonWriter::ObjectScope valueRoot(json); - PrintTypeName(*this, id, hasSymbols, true, json); + PrintTypeName(*this, id, hasSymbols, settings, json); } }); - json.Array("Types", [this, &json, hasSymbols] { + json.Array("Types", [this, &json, hasSymbols, &settings] { for (uint32_t i = 0; i < uint32_t(Types.size()); ++i) { JsonWriter::ObjectScope nodeRoot(json); - PrintType(*this, i, hasSymbols, true, json, false); + PrintType(*this, i, hasSymbols, settings, json, false); } }); - json.Array("Buffers", [this, &json, hasSymbols] { + json.Array("Buffers", [this, &json, hasSymbols, &settings] { for (uint32_t i = 0; i < uint32_t(Buffers.size()); ++i) - PrintBuffer(*this, i, hasSymbols, true, json); + PrintBuffer(*this, i, hasSymbols, settings, json); }); json.Array("Statements", [this, &json] { @@ -1427,7 +1418,7 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons else PrintChildren(*this, json, "Children", 1, Nodes.size(), - HideFileInfo, true); + settings); } return json.str(); From 9b628e7b2e81ebb4e3ea829891d3e584faa10e81 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 11 Nov 2025 12:21:02 +0100 Subject: [PATCH 101/126] Fixed invalid UnderlyingName for builtin objects if the sugared and desugared type mismatch --- tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 8679ad46c6..5e5064124e 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -735,6 +735,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, type = svt; cls = D3D_SVC_OBJECT; + underlyingName = name; innerTypeName = "$Element"; From ab2f1b3131b55caf9e9a12baa44b1013d898d344 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 11 Nov 2025 12:43:31 +0100 Subject: [PATCH 102/126] Now added ability to know the inner type of sbuffer/cbuffer/textures passed to functions --- .../DxcReflectionJson.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 115fd49ff0..2b6714d754 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -695,16 +695,33 @@ static void PrintTypeName(const ReflectionData &Reflection, uint32_t TypeId, } else { + const ReflectionVariableTypeSymbol &symbol = Reflection.TypeSymbols[TypeId]; + name = Reflection.Strings[symbol.DisplayNameId]; - FillArraySizes(Reflection, symbol.DisplayArray, arraySizes); underlyingName = Reflection.Strings[symbol.UnderlyingNameId]; + + FillArraySizes(Reflection, symbol.DisplayArray, arraySizes); FillArraySizes(Reflection, type.GetUnderlyingArray(), underlyingArraySizes); } if (name.size()) Json.StringField(NameForTypeName, name); + if (type.GetClass() == D3D_SVC_OBJECT && + type.GetType() != D3D_SVT_BYTEADDRESS_BUFFER && + type.GetType() != D3D_SVT_RWBYTEADDRESS_BUFFER && + type.GetMemberCount() == 1) { + + uint32_t innerTypeId = Reflection.MemberTypeIds[type.GetMemberStart()]; + + Json.Array( + "Args", [&Json, &Reflection, innerTypeId, HasSymbols, &Settings]() { + JsonWriter::ObjectScope scope(Json); + PrintTypeName(Reflection, innerTypeId, HasSymbols, Settings, Json); + }); + } + if (arraySizes.size()) Json.Array("ArraySize", [&arraySizes, &Json]() { for (uint32_t i : arraySizes) From 71aebb874f2d80189413bc7e07c20a0b36a4e3dc Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 11 Nov 2025 13:00:11 +0100 Subject: [PATCH 103/126] Exposed BaseClass/Interfaces to 'Class' attribute in nodes for structs/unions --- .../DxcReflectionJson.cpp | 104 +++++++++++------- 1 file changed, 63 insertions(+), 41 deletions(-) diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 2b6714d754..596888169a 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -1133,65 +1133,82 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, uint32_t childrenToSkip = 0; - // Function - - if (nodeType == D3D12_HLSL_NODE_TYPE_FUNCTION) - Json.Object("Function", [&node, &Reflection, &Json, - &Settings, &childrenToSkip]() { - ReflectionFunction func = Reflection.Functions[node.GetLocalId()]; - PrintFunction(Json, Reflection, node.GetLocalId(), Settings); - childrenToSkip = func.GetNumParameters() + func.HasReturn(); - }); - - // Register + bool recurseType = false; + const char *stmtType = nullptr; - if (nodeType == D3D12_HLSL_NODE_TYPE_REGISTER) - Json.Object("Register", [&node, &Reflection, &Json, &Settings]() { - PrintRegister(Json, Reflection, node.GetLocalId(), Settings); - }); + switch (nodeType) { - // Enum + case D3D12_HLSL_NODE_TYPE_FUNCTION: + Json.Object( + "Function", [&node, &Reflection, &Json, &Settings, &childrenToSkip]() { + ReflectionFunction func = Reflection.Functions[node.GetLocalId()]; + PrintFunction(Json, Reflection, node.GetLocalId(), Settings); + childrenToSkip = func.GetNumParameters() + func.HasReturn(); + }); + break; - if (nodeType == D3D12_HLSL_NODE_TYPE_ENUM) - Json.Object("Enum", [&node, &Reflection, &Json, &Settings, - &childrenToSkip]() { - PrintEnum(Json, Reflection, node.GetLocalId(), Settings); - childrenToSkip = node.GetChildCount(); + case D3D12_HLSL_NODE_TYPE_REGISTER: + Json.Object("Register", [&node, &Reflection, &Json, &Settings]() { + PrintRegister(Json, Reflection, node.GetLocalId(), Settings); }); + break; - // Type + case D3D12_HLSL_NODE_TYPE_ENUM: + Json.Object("Enum", + [&node, &Reflection, &Json, &Settings, &childrenToSkip]() { + PrintEnum(Json, Reflection, node.GetLocalId(), Settings); + childrenToSkip = node.GetChildCount(); + }); + break; - bool isType = false; - bool recurseType = false; + case D3D12_HLSL_NODE_TYPE_STRUCT: + case D3D12_HLSL_NODE_TYPE_UNION: { + + if (node.IsFwdDeclare()) + break; + + const ReflectionVariableType &type = Reflection.Types[node.GetLocalId()]; + + if (type.GetBaseClass() != uint32_t(-1) || type.GetInterfaceCount()) + Json.Object("Class", [&Json, &type, &Reflection, hasSymbols, + &Settings]() { + if (type.GetBaseClass() != uint32_t(-1)) + Json.Object("BaseClass", + [&Json, &type, &Reflection, hasSymbols, &Settings]() { + PrintTypeName(Reflection, type.GetBaseClass(), + hasSymbols, Settings, Json); + }); + + if (type.GetInterfaceCount()) + Json.Array("Interfaces", [&Json, &type, &Reflection, hasSymbols, + &Settings]() { + for (uint32_t i = 0; i < uint32_t(type.GetInterfaceCount()); ++i) { + uint32_t interfaceId = type.GetInterfaceStart() + i; + JsonWriter::ObjectScope nodeRoot(Json); + PrintTypeName(Reflection, Reflection.TypeList[interfaceId], + hasSymbols, Settings, Json); + } + }); + }); + + break; + } - switch (nodeType) { case D3D12_HLSL_NODE_TYPE_VARIABLE: case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: case D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE: recurseType = true; - isType = true; - break; + [[fallthrough]]; case D3D12_HLSL_NODE_TYPE_TYPEDEF: - isType = true; - break; - } - if (isType) - Json.Object("Type", [&node, &Reflection, &Json, &Settings, - hasSymbols, recurseType]() { + Json.Object("Type", [&node, &Reflection, &Json, &Settings, hasSymbols, + recurseType]() { PrintType(Reflection, node.GetLocalId(), hasSymbols, Settings, Json, recurseType); }); - // If; turns into ("Condition"), ("Body"), ("Else") - // While; turns into ("Condition"), ("Body") - // For; turns into ("Condition"), ("Init"), ("Body") - // Switch; turns into ("Condition"), ("Body") - - const char *stmtType = nullptr; - - switch (nodeType) { + break; case D3D12_HLSL_NODE_TYPE_IF: stmtType = "If"; @@ -1210,6 +1227,11 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, break; } + // If; turns into ("Condition"), ("Body"), ("Else") + // While; turns into ("Condition"), ("Body") + // For; turns into ("Condition"), ("Init"), ("Body") + // Switch; turns into ("Condition"), ("Body") + if (stmtType) { Json.Object(stmtType, [&node, &Reflection, &Json, &Settings, NodeId, From f9b3454c70d47780be2dd5b5e2f373445cf72477 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 11 Nov 2025 14:52:26 +0100 Subject: [PATCH 104/126] Fixed linux build by separating the function from the error string, adding INT64 to WinAdapter and fixing WinAdapter includes for d3d12shader.h. All reflection targets are now (almost) the highest error level. Fixed build issues. --- .../DxcReflection/DxcReflectionContainer.h | 59 ++++++++++++++----- include/dxc/Support/ErrorCodes.h | 3 +- include/dxc/WinAdapter.h | 1 + include/dxc/dxcreflect.h | 13 +++- .../clang/tools/dxcreflection/CMakeLists.txt | 6 ++ .../dxcreflection/dxcreflection_from_ast.cpp | 8 +-- .../tools/dxcreflection/dxcreflector.cpp | 18 ++---- .../dxcreflectioncontainer/CMakeLists.txt | 6 ++ .../DxcReflectionContainer.cpp | 2 + tools/clang/tools/dxreflector/CMakeLists.txt | 6 ++ tools/clang/tools/dxreflector/dxreflector.cpp | 6 +- 11 files changed, 91 insertions(+), 37 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflectionContainer.h b/include/dxc/DxcReflection/DxcReflectionContainer.h index 93dc21a440..93e2dabe9e 100644 --- a/include/dxc/DxcReflection/DxcReflectionContainer.h +++ b/include/dxc/DxcReflection/DxcReflectionContainer.h @@ -15,6 +15,16 @@ #include #include +#ifndef _WIN32 + #include "dxc/WinAdapter.h" + // need to disable this as it is voilated by this header + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" + // Need to instruct non-windows compilers on what an interface is + #define interface struct +#endif + +#include "dxc/dxcapi.h" #include "d3d12shader.h" #include "dxc/dxcreflect.h" @@ -25,24 +35,41 @@ namespace hlsl { struct ReflectionError { const char *err; + const char *func; uint32_t index; //For example which elementId made this error bool hasIndex; uint8_t pad[3]; constexpr ReflectionError() - : err(nullptr), index(0), hasIndex(false), pad{0, 0, 0} {} + : err(nullptr), func(nullptr), index(0), hasIndex(false), pad{0, 0, 0} {} + + constexpr ReflectionError(const char *err, const char *func) + : err(err), func(func), index(0), hasIndex(false), pad{0, 0, 0} {} + + constexpr ReflectionError(const char *err, const char *func, uint32_t index) + : err(err), func(func), index(index), hasIndex(true), pad{0, 0, 0} {} + + std::string toString() const { - constexpr ReflectionError(const char *err) - : err(err), index(0), hasIndex(false), pad{0, 0, 0} {} + if(!err) + return ""; - constexpr ReflectionError(const char *err, uint32_t index) - : err(err), index(index), hasIndex(true), pad{0, 0, 0} {} + std::string res = err; + + if(hasIndex) + res += " (at index " + std::to_string(index) + ")"; + + if(func) + res += " (" + std::string(func) + ")"; + + return res; + } - operator const char *() const { return err; } + operator bool() const { return err; } }; -static constexpr const ReflectionError ReflectionErrorSuccess = nullptr; +static constexpr const ReflectionError ReflectionErrorSuccess = {}; #ifndef NDEBUG #if defined(_MSC_VER) @@ -54,9 +81,9 @@ static constexpr const ReflectionError ReflectionErrorSuccess = nullptr; #endif #define HLSL_REFL_ERR_STRING(x) #x #define HLSL_REFL_ERR_STRING2(x) HLSL_REFL_ERR_STRING(x) - #define HLSL_REFL_ERR(x, ...) ReflectionError(x " at " __FILE__ ":" HLSL_REFL_ERR_STRING2(__LINE__) " (" HLSL_REFL_ERR_FUNC_NAME ")", __VA_ARGS__) + #define HLSL_REFL_ERR(x, ...) ReflectionError(x " at " __FILE__ ":" HLSL_REFL_ERR_STRING2(__LINE__), HLSL_REFL_ERR_FUNC_NAME, ##__VA_ARGS__) #else - #define HLSL_REFL_ERR(x, ...) ReflectionError(x, __VA_ARGS__) + #define HLSL_REFL_ERR(x, ...) ReflectionError(x, nullptr, ##__VA_ARGS__) #endif class ReflectionNode { @@ -97,8 +124,9 @@ class ReflectionNode { uint32_t ParentId, uint8_t AnnotationCount, uint16_t SemanticId) : LocalIdParentLo(LocalId | (ParentId << 24)), ParentHi(ParentId >> 8), Annotations(AnnotationCount), Type(NodeType), - ChildCountFwdBckLo(ChildCount | (0xFFu << 24)), FwdBckHi(0xFFFF), - AnnotationStart(AnnotationStart), SemanticId(SemanticId), Padding(0) { + ChildCountFwdBckLo(ChildCount | (0xFFu << 24)), + AnnotationStart(AnnotationStart), FwdBckHi(0xFFFF), + SemanticId(SemanticId), Padding(0) { if (IsFwdDeclare) Type |= 0x80; @@ -477,8 +505,8 @@ class ReflectionShaderResource { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, uint32_t uFlags, D3D_RESOURCE_RETURN_TYPE ReturnType, D3D_SRV_DIMENSION Dimension, uint32_t NodeId, uint32_t ArrayId, uint32_t BufferId) - : Type(Type), BindCount(BindCount), uFlags(uFlags), - ReturnType(ReturnType), Dimension(Dimension), NodeId(NodeId), + : Type(Type), Dimension(Dimension), ReturnType(ReturnType), uFlags(uFlags), + BindCount(BindCount), Pad(0), NodeId(NodeId), ArrayId(ArrayId), BufferId(BufferId) {} public: @@ -621,8 +649,9 @@ class ReflectionVariableType { // Almost maps to CShaderReflectionType and uint32_t InterfaceCount) : MemberData(MembersStart | (MembersCount << 24)), Class(Class), Type(Type), Rows(Rows), Columns(Columns), - UnderlyingArray(ElementsOrArrayIdUnderlying), BaseClass(BaseClass), - InterfaceOffsetAndCount(InterfaceOffset | (InterfaceCount << 24)) {} + BaseClass(BaseClass), + InterfaceOffsetAndCount(InterfaceOffset | (InterfaceCount << 24)), + UnderlyingArray(ElementsOrArrayIdUnderlying) {} public: bool operator==(const ReflectionVariableType &Other) const { diff --git a/include/dxc/Support/ErrorCodes.h b/include/dxc/Support/ErrorCodes.h index 5239c8118c..d49ab29210 100644 --- a/include/dxc/Support/ErrorCodes.h +++ b/include/dxc/Support/ErrorCodes.h @@ -157,4 +157,5 @@ // 0X80AA001F - DXIL container Program Version mismatches Dxil module shader // model #define DXC_E_INCORRECT_PROGRAM_VERSION \ - DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR, FACILITY_DXC, (0x001F)) \ No newline at end of file + DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR, FACILITY_DXC, (0x001F)) + \ No newline at end of file diff --git a/include/dxc/WinAdapter.h b/include/dxc/WinAdapter.h index d02ad1ac38..908408f558 100644 --- a/include/dxc/WinAdapter.h +++ b/include/dxc/WinAdapter.h @@ -321,6 +321,7 @@ typedef DWORD *LPDWORD; typedef uint32_t UINT32; typedef uint64_t UINT64; +typedef int64_t INT64; typedef signed char INT8, *PINT8; typedef signed int INT32, *PINT32; diff --git a/include/dxc/dxcreflect.h b/include/dxc/dxcreflect.h index 6015853f0e..2104c7d0d4 100644 --- a/include/dxc/dxcreflect.h +++ b/include/dxc/dxcreflect.h @@ -12,7 +12,16 @@ #ifndef __DXC_REFLECT__ #define __DXC_REFLECT__ -#include +#ifndef _WIN32 + #include "dxc/WinAdapter.h" + // need to disable this as it is voilated by this header + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" + // Need to instruct non-windows compilers on what an interface is + #define interface struct +#endif + +#include "dxc/dxcapi.h" #include "d3d12shader.h" #ifdef _MSC_VER @@ -197,7 +206,7 @@ typedef struct _D3D12_SHADER_TYPE_DESC1 { } D3D12_SHADER_TYPE_DESC1; DECLARE_INTERFACE_(ID3D12ShaderReflectionType1, ID3D12ShaderReflectionType) { - STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_TYPE_DESC1 *pDesc) PURE; + STDMETHOD(GetDesc1)(THIS_ _Out_ D3D12_SHADER_TYPE_DESC1 *pDesc) PURE; STDMETHOD(GetArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) PURE; STDMETHOD(GetDisplayArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) PURE; }; diff --git a/tools/clang/tools/dxcreflection/CMakeLists.txt b/tools/clang/tools/dxcreflection/CMakeLists.txt index 03d340ca58..f9bc1ea44d 100644 --- a/tools/clang/tools/dxcreflection/CMakeLists.txt +++ b/tools/clang/tools/dxcreflection/CMakeLists.txt @@ -13,3 +13,9 @@ add_clang_library(dxcreflection STATIC dxcreflection_from_ast.cpp) target_link_libraries(dxcreflection PRIVATE ${LIBRARIES} dxcreflectioncontainer) + +if(MSVC) + target_compile_options(dxcreflection PRIVATE /W4 /WX) +else() + target_compile_options(dxcreflection PRIVATE -Wall -Wextra -Werror -Wno-pedantic) +endif() diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 5e5064124e..1610a6e8db 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -16,7 +16,7 @@ #include "clang/AST/DeclVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/Frontend/CompilerInstance.h" -#include "clang/basic/SourceManager.h" +#include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" #include "dxc/DxcReflection/DxcReflectionContainer.h" @@ -24,7 +24,7 @@ using namespace clang; namespace hlsl { -static [[nodiscard]] ReflectionError +[[nodiscard]] static ReflectionError PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, const LangOptions &LangOpts, const std::string &UnqualifiedName, const Decl *DeclSelf, D3D12_HLSL_NODE_TYPE Type, @@ -339,7 +339,7 @@ static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, uint32_t dimensions; - if (const BuiltinType *bt = dyn_cast(desugared)) + if (isa(desugared)) dimensions = 1; else { @@ -1624,7 +1624,7 @@ class RecursiveReflector : public DeclVisitor { uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls) - : Ctx(Ctx), ASTCtx(ASTCtx), Diags(Diags), SM(SM), Refl(Refl), + : Ctx(Ctx), ASTCtx(ASTCtx), SM(SM), Diags(Diags), Refl(Refl), AutoBindingSpace(AutoBindingSpace), Depth(Depth), Features(Features), ParentNodeId(ParentNodeId), DefaultRowMaj(DefaultRowMaj), FwdDecls(FwdDecls){} diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 725ee3ee91..32b6744b8e 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -323,12 +323,10 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { return S_OK; } - STDMETHOD(GetDesc)(D3D12_SHADER_TYPE_DESC1 *pDesc) override { + STDMETHOD(GetDesc1)(D3D12_SHADER_TYPE_DESC1 *pDesc) override { IFR(ZeroMemoryToOut(pDesc)); - const ReflectionVariableType &type = m_Data->Types[m_TypeId]; - GetDesc(&pDesc->Desc); pDesc->DisplayName = m_NameDisplay.c_str(); pDesc->DisplayElements = m_ElementsDisplay; @@ -550,7 +548,7 @@ class CHLSLReflectionConstantBuffer final m_VariablesByName.clear(); m_Variables.resize(children.size()); - for (uint32_t i = 0, j = 0; i < m_ChildCount; ++i) { + for (uint32_t i = 0; i < m_ChildCount; ++i) { uint32_t childId = children[i]; @@ -584,12 +582,10 @@ class CHLSLReflectionConstantBuffer final m_VariablesByName.clear(); m_Variables.resize(Globals.size()); - for (uint32_t i = 0, j = 0; i < m_ChildCount; ++i) { + for (uint32_t i = 0; i < m_ChildCount; ++i) { uint32_t childId = Globals[i]; - const ReflectionNode &node = Data.Nodes[childId]; - std::string name; if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) @@ -1570,8 +1566,6 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, if (astHelper.bHasErrors) return E_FAIL; - TranslationUnitDecl *tu = astHelper.tu; - D3D12_HLSL_REFLECTION_FEATURE reflectMask = D3D12_HLSL_REFLECTION_FEATURE_NONE; @@ -1601,7 +1595,7 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, if (ReflectionError err = DxcHLSLReflectionDataFromAST( refl, astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, reflectMask, opts.DefaultRowMajor)) { - fprintf(stderr, "DxcHLSLReflectionDataFromAST failed %s\n", err.err); + fprintf(stderr, "DxcHLSLReflectionDataFromAST failed %s\n", err.toString().c_str()); return E_FAIL; } @@ -1620,7 +1614,7 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, ReflectionData deserialized; if (ReflectionError err = deserialized.Deserialize(bytes, true)) { - fprintf(stderr, "Deserialize failed %s\n", err.err); + fprintf(stderr, "Deserialize failed %s\n", err.toString().c_str()); return E_FAIL; } @@ -1641,7 +1635,7 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, ReflectionData deserialized2; if (ReflectionError err = deserialized2.Deserialize(bytes, true)) { - fprintf(stderr, "Deserialize failed %s\n", err.err); + fprintf(stderr, "Deserialize failed %s\n", err.toString().c_str()); return E_FAIL; } diff --git a/tools/clang/tools/dxcreflectioncontainer/CMakeLists.txt b/tools/clang/tools/dxcreflectioncontainer/CMakeLists.txt index 015d691afa..474ee0ac02 100644 --- a/tools/clang/tools/dxcreflectioncontainer/CMakeLists.txt +++ b/tools/clang/tools/dxcreflectioncontainer/CMakeLists.txt @@ -2,3 +2,9 @@ # This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. add_clang_library(dxcreflectioncontainer STATIC DxcReflectionContainer.cpp DxcReflectionJson.cpp) + +if(MSVC) + target_compile_options(dxcreflectioncontainer PRIVATE /W4 /WX) +else() + target_compile_options(dxcreflectioncontainer PRIVATE -Wall -Wextra -Werror -Wno-pedantic) +endif() diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index b47e41671c..7288d879e7 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -681,6 +681,8 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { return HLSL_REFL_ERR("Node is a parameter, typedef, variable or " "static variable but also has children", i); + [[fallthrough]]; + case D3D12_HLSL_NODE_TYPE_IF: case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: diff --git a/tools/clang/tools/dxreflector/CMakeLists.txt b/tools/clang/tools/dxreflector/CMakeLists.txt index 590fe03c0c..6e938f8b78 100644 --- a/tools/clang/tools/dxreflector/CMakeLists.txt +++ b/tools/clang/tools/dxreflector/CMakeLists.txt @@ -38,3 +38,9 @@ endif() install(TARGETS dxreflector RUNTIME DESTINATION bin) +if(MSVC) + target_compile_options(dxreflector PRIVATE /W4 /WX) +else() + target_compile_options(dxreflector PRIVATE -Wall -Wextra -Werror -Wno-pedantic) +endif() + diff --git a/tools/clang/tools/dxreflector/dxreflector.cpp b/tools/clang/tools/dxreflector/dxreflector.cpp index 5055d1ad5f..67f4172017 100644 --- a/tools/clang/tools/dxreflector/dxreflector.cpp +++ b/tools/clang/tools/dxreflector/dxreflector.cpp @@ -84,7 +84,7 @@ int main(int argc, const char **argv) { argStrings.Utf8CharPtrVector.resize( argStrings.Utf8CharPtrVector.size() + 2); - for (int i = 0; i < argStrings.Utf8StringVector.size(); ++i) + for (uint64_t i = 0; i < argStrings.Utf8StringVector.size(); ++i) argStrings.Utf8CharPtrVector[i] = argStrings.Utf8StringVector[i].c_str(); } @@ -179,8 +179,8 @@ int main(int argc, const char **argv) { wargs.reserve(argStrings.Utf8CharPtrVector.size()); wargsC.reserve(argStrings.Utf8CharPtrVector.size()); - for (const std::string &arg : argStrings.Utf8CharPtrVector) { - wargs.push_back(std::wstring(CA2W(arg.c_str()))); + for (const char *arg : argStrings.Utf8CharPtrVector) { + wargs.push_back(std::wstring(CA2W(arg))); wargsC.push_back(wargs.back().c_str()); } From 34cd641ac8b0117018433e03e4ea785b6a7feade Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 11 Nov 2025 16:18:43 +0100 Subject: [PATCH 105/126] Fixed windows build and removed printing reflection binary size to produce a valid json --- include/dxc/DxcReflection/DxcReflectionContainer.h | 1 - tools/clang/tools/dxcreflection/dxcreflector.cpp | 4 ---- 2 files changed, 5 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflectionContainer.h b/include/dxc/DxcReflection/DxcReflectionContainer.h index 93e2dabe9e..ab7d4b7bfb 100644 --- a/include/dxc/DxcReflection/DxcReflectionContainer.h +++ b/include/dxc/DxcReflection/DxcReflectionContainer.h @@ -24,7 +24,6 @@ #define interface struct #endif -#include "dxc/dxcapi.h" #include "d3d12shader.h" #include "dxc/dxcreflect.h" diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 32b6744b8e..7017e6708e 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -1623,8 +1623,6 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, return E_FAIL; } - printf("Reflection binary size: %" PRIu64 "\n", bytes.size()); - // Test stripping symbols if (!opts.ReflOpt.DisableSymbols) { @@ -1643,8 +1641,6 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, fprintf(stderr, "Dump or Deserialize doesn't match\n"); return E_FAIL; } - - printf("Stripped reflection size: %" PRIu64 "\n", bytes.size()); } #endif From 9e75661adc5417f07262686f6ec9403946236ee3 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 11 Nov 2025 16:34:23 +0100 Subject: [PATCH 106/126] Applied clang format to everything except *_ast.cpp since the include order changing fails the compile --- .../DxcReflection/DxcReflectionContainer.h | 144 +++--- include/dxc/dxcreflect.h | 114 +++-- lib/DxcSupport/HLSLOptions.cpp | 3 +- .../tools/dxcreflection/dxcreflector.cpp | 224 +++++---- .../DxcReflectionContainer.cpp | 442 +++++++++--------- .../DxcReflectionJson.cpp | 111 ++--- tools/clang/tools/dxreflector/dxreflector.cpp | 48 +- 7 files changed, 549 insertions(+), 537 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflectionContainer.h b/include/dxc/DxcReflection/DxcReflectionContainer.h index ab7d4b7bfb..1fec974530 100644 --- a/include/dxc/DxcReflection/DxcReflectionContainer.h +++ b/include/dxc/DxcReflection/DxcReflectionContainer.h @@ -9,19 +9,19 @@ #pragma once -#include -#include -#include #include #include +#include +#include +#include #ifndef _WIN32 - #include "dxc/WinAdapter.h" - // need to disable this as it is voilated by this header - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" - // Need to instruct non-windows compilers on what an interface is - #define interface struct +#include "dxc/WinAdapter.h" +// need to disable this as it is voilated by this header +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +// Need to instruct non-windows compilers on what an interface is +#define interface struct #endif #include "d3d12shader.h" @@ -36,7 +36,7 @@ struct ReflectionError { const char *err; const char *func; - uint32_t index; //For example which elementId made this error + uint32_t index; // For example which elementId made this error bool hasIndex; uint8_t pad[3]; @@ -51,15 +51,15 @@ struct ReflectionError { std::string toString() const { - if(!err) + if (!err) return ""; std::string res = err; - if(hasIndex) + if (hasIndex) res += " (at index " + std::to_string(index) + ")"; - if(func) + if (func) res += " (" + std::string(func) + ")"; return res; @@ -71,23 +71,25 @@ struct ReflectionError { static constexpr const ReflectionError ReflectionErrorSuccess = {}; #ifndef NDEBUG - #if defined(_MSC_VER) - #define HLSL_REFL_ERR_FUNC_NAME __FUNCTION__ - #elif defined(__clang__) || defined(__GNUC__) - #define HLSL_REFL_ERR_FUNC_NAME __PRETTY_FUNCTION__ - #else - #define HLSL_REFL_ERR_FUNC_NAME __func__ - #endif - #define HLSL_REFL_ERR_STRING(x) #x - #define HLSL_REFL_ERR_STRING2(x) HLSL_REFL_ERR_STRING(x) - #define HLSL_REFL_ERR(x, ...) ReflectionError(x " at " __FILE__ ":" HLSL_REFL_ERR_STRING2(__LINE__), HLSL_REFL_ERR_FUNC_NAME, ##__VA_ARGS__) +#if defined(_MSC_VER) +#define HLSL_REFL_ERR_FUNC_NAME __FUNCTION__ +#elif defined(__clang__) || defined(__GNUC__) +#define HLSL_REFL_ERR_FUNC_NAME __PRETTY_FUNCTION__ +#else +#define HLSL_REFL_ERR_FUNC_NAME __func__ +#endif +#define HLSL_REFL_ERR_STRING(x) #x +#define HLSL_REFL_ERR_STRING2(x) HLSL_REFL_ERR_STRING(x) +#define HLSL_REFL_ERR(x, ...) \ + ReflectionError(x " at " __FILE__ ":" HLSL_REFL_ERR_STRING2(__LINE__), \ + HLSL_REFL_ERR_FUNC_NAME, ##__VA_ARGS__) #else - #define HLSL_REFL_ERR(x, ...) ReflectionError(x, nullptr, ##__VA_ARGS__) +#define HLSL_REFL_ERR(x, ...) ReflectionError(x, nullptr, ##__VA_ARGS__) #endif class ReflectionNode { - uint32_t LocalIdParentLo; //24 : 8 + uint32_t LocalIdParentLo; // 24 : 8 union { uint32_t ParentHiAnnotationsType32; @@ -98,7 +100,7 @@ class ReflectionNode { }; }; - uint32_t ChildCountFwdBckLo; //24 : 8 + uint32_t ChildCountFwdBckLo; // 24 : 8 union { uint32_t AnnotationStartFwdBckHi; @@ -116,30 +118,29 @@ class ReflectionNode { ChildCountFwdBckLo &= 0xFFFFFF; ChildCountFwdBckLo |= v << 24; } - - ReflectionNode(D3D12_HLSL_NODE_TYPE NodeType, - bool IsFwdDeclare, - uint32_t LocalId, uint16_t AnnotationStart, uint32_t ChildCount, - uint32_t ParentId, uint8_t AnnotationCount, uint16_t SemanticId) + + ReflectionNode(D3D12_HLSL_NODE_TYPE NodeType, bool IsFwdDeclare, + uint32_t LocalId, uint16_t AnnotationStart, + uint32_t ChildCount, uint32_t ParentId, + uint8_t AnnotationCount, uint16_t SemanticId) : LocalIdParentLo(LocalId | (ParentId << 24)), ParentHi(ParentId >> 8), - Annotations(AnnotationCount), Type(NodeType), - ChildCountFwdBckLo(ChildCount | (0xFFu << 24)), - AnnotationStart(AnnotationStart), FwdBckHi(0xFFFF), - SemanticId(SemanticId), Padding(0) { + Annotations(AnnotationCount), Type(NodeType), + ChildCountFwdBckLo(ChildCount | (0xFFu << 24)), + AnnotationStart(AnnotationStart), FwdBckHi(0xFFFF), + SemanticId(SemanticId), Padding(0) { if (IsFwdDeclare) Type |= 0x80; } public: - ReflectionNode() = default; [[nodiscard]] static ReflectionError Initialize(ReflectionNode &OutNode, D3D12_HLSL_NODE_TYPE NodeType, - bool IsFwdDeclare, - uint32_t LocalId, uint16_t AnnotationStart, uint32_t ChildCount, - uint32_t ParentId, uint8_t AnnotationCount, uint16_t SemanticId) { + bool IsFwdDeclare, uint32_t LocalId, uint16_t AnnotationStart, + uint32_t ChildCount, uint32_t ParentId, uint8_t AnnotationCount, + uint16_t SemanticId) { if (NodeType < D3D12_HLSL_NODE_TYPE_START || NodeType > D3D12_HLSL_NODE_TYPE_END) @@ -155,10 +156,10 @@ class ReflectionNode { return HLSL_REFL_ERR("ChildCount out of bounds"); if (IsFwdDeclare && AnnotationCount) - return HLSL_REFL_ERR("Fwd declares aren't allowed to have annotations"); + return HLSL_REFL_ERR("Fwd declares aren't allowed to have annotations"); OutNode = ReflectionNode(NodeType, IsFwdDeclare, LocalId, AnnotationStart, - ChildCount, ParentId, AnnotationCount, SemanticId); + ChildCount, ParentId, AnnotationCount, SemanticId); return ReflectionErrorSuccess; } @@ -177,7 +178,7 @@ class ReflectionNode { // !IsFwdDeclare() && IsFwdDefined(): GetFwdBck() should point to a valid fwd // declare that points back to it. // Backwards declare should point to a NodeId < self and Forwards to > self. - // Forward declares aren't allowed to have any children except functions, + // Forward declares aren't allowed to have any children except functions, // which can have parameters only (inc. return). // If there's a name, they should match. // Must be same node type too. @@ -190,8 +191,8 @@ class ReflectionNode { bool IsFwdBckDefined() const { return GetFwdBck() != ((1 << 24) - 1); } [[nodiscard]] ReflectionError ResolveFwdDeclare(uint32_t SelfId, - ReflectionNode &Definition, - uint32_t DefinitionId) { + ReflectionNode &Definition, + uint32_t DefinitionId) { if (SelfId >= ((1u << 24) - 1)) return HLSL_REFL_ERR("SelfId out of bounds"); @@ -257,7 +258,7 @@ class ReflectionNodeSymbol { struct { uint32_t NameId; // Local name (not including parent's name) - uint16_t FileSourceId; //-1 == no file info + uint16_t FileSourceId; //-1 == no file info uint16_t SourceLineCount; }; uint64_t NameIdFileNameIdSourceLineCount; @@ -271,10 +272,10 @@ class ReflectionNodeSymbol { }; uint64_t SourceColumnStartEndLo; }; - + ReflectionNodeSymbol(uint32_t NameId, uint16_t FileSourceId, - uint16_t SourceLineCount, uint32_t SourceLineStart, - uint32_t SourceColumnStart, uint32_t SourceColumnEnd) + uint16_t SourceLineCount, uint32_t SourceLineStart, + uint32_t SourceColumnStart, uint32_t SourceColumnEnd) : NameId(NameId), FileSourceId(FileSourceId), SourceLineCount(SourceLineCount), SourceColumnStartLo(uint16_t(SourceColumnStart)), @@ -284,13 +285,13 @@ class ReflectionNodeSymbol { (SourceLineStart << 12)) {} public: - ReflectionNodeSymbol() = default; [[nodiscard]] static ReflectionError - Initialize(ReflectionNodeSymbol &Symbol, uint32_t NameId, uint16_t FileSourceId, - uint16_t SourceLineCount, uint32_t SourceLineStart, - uint32_t SourceColumnStart, uint32_t SourceColumnEnd) { + Initialize(ReflectionNodeSymbol &Symbol, uint32_t NameId, + uint16_t FileSourceId, uint16_t SourceLineCount, + uint32_t SourceLineStart, uint32_t SourceColumnStart, + uint32_t SourceColumnEnd) { if (SourceColumnStart >= (1u << 22)) return HLSL_REFL_ERR("SourceColumnStart out of bounds"); @@ -301,13 +302,12 @@ class ReflectionNodeSymbol { if (SourceLineStart >= ((1u << 20) - 1)) return HLSL_REFL_ERR("SourceLineStart out of bounds"); - Symbol = - ReflectionNodeSymbol(NameId, FileSourceId, SourceLineCount, - SourceLineStart, SourceColumnStart, SourceColumnEnd); + Symbol = ReflectionNodeSymbol(NameId, FileSourceId, SourceLineCount, + SourceLineStart, SourceColumnStart, + SourceColumnEnd); return ReflectionErrorSuccess; } - uint32_t GetNameId() const { return NameId; } uint16_t GetFileSourceId() const { return FileSourceId; } @@ -349,8 +349,7 @@ struct ReflectionEnumValue { uint32_t NodeId; bool operator==(const ReflectionEnumValue &other) const { - return Value == other.Value && - NodeId == other.NodeId; + return Value == other.Value && NodeId == other.NodeId; } }; @@ -370,8 +369,8 @@ struct ReflectionFunctionParameter { // Mirrors D3D12_PARAMETER_DESC without } }; -// A statement is a for, while, if, switch. Basically every Stmt except do or scope. -// It can contain the following child nodes: +// A statement is a for, while, if, switch. Basically every Stmt except do or +// scope. It can contain the following child nodes: // - if HasConditionVar(): a variable in the condition // - NodeCount children (If: children ex. else body, For: init children) // - Rest of the body (If: else body, otherwise: normal body) @@ -504,8 +503,8 @@ class ReflectionShaderResource { // Almost maps to D3D12_SHADER_INPUT_BIND_DESC, uint32_t uFlags, D3D_RESOURCE_RETURN_TYPE ReturnType, D3D_SRV_DIMENSION Dimension, uint32_t NodeId, uint32_t ArrayId, uint32_t BufferId) - : Type(Type), Dimension(Dimension), ReturnType(ReturnType), uFlags(uFlags), - BindCount(BindCount), Pad(0), NodeId(NodeId), + : Type(Type), Dimension(Dimension), ReturnType(ReturnType), + uFlags(uFlags), BindCount(BindCount), Pad(0), NodeId(NodeId), ArrayId(ArrayId), BufferId(BufferId) {} public: @@ -565,10 +564,10 @@ class ReflectionArray { : ArrayElemStart((ArrayElem << 26) | ArrayStart) {} public: - ReflectionArray() = default; - [[nodiscard]] static ReflectionError Initialize(ReflectionArray &Arr, uint32_t ArrayElem, uint32_t ArrayStart) { + [[nodiscard]] static ReflectionError + Initialize(ReflectionArray &Arr, uint32_t ArrayElem, uint32_t ArrayStart) { if (ArrayElem <= 1 || ArrayElem > 32) return HLSL_REFL_ERR("ArrayElem out of bounds"); @@ -647,8 +646,7 @@ class ReflectionVariableType { // Almost maps to CShaderReflectionType and uint32_t MembersStart, uint32_t InterfaceOffset, uint32_t InterfaceCount) : MemberData(MembersStart | (MembersCount << 24)), Class(Class), - Type(Type), Rows(Rows), Columns(Columns), - BaseClass(BaseClass), + Type(Type), Rows(Rows), Columns(Columns), BaseClass(BaseClass), InterfaceOffsetAndCount(InterfaceOffset | (InterfaceCount << 24)), UnderlyingArray(ElementsOrArrayIdUnderlying) {} @@ -740,8 +738,9 @@ struct ReflectionVariableTypeSymbol { } ReflectionVariableTypeSymbol() = default; - ReflectionVariableTypeSymbol(ReflectionArrayOrElements ElementsOrArrayIdDisplay, - uint32_t DisplayNameId, uint32_t UnderlyingNameId) + ReflectionVariableTypeSymbol( + ReflectionArrayOrElements ElementsOrArrayIdDisplay, + uint32_t DisplayNameId, uint32_t UnderlyingNameId) : DisplayArray(ElementsOrArrayIdDisplay), DisplayNameId(DisplayNameId), UnderlyingNameId(UnderlyingNameId) {} }; @@ -791,10 +790,11 @@ class ReflectionAnnotation { } }; -//Note: Regarding nodes, node 0 is the root node (global scope) -// If a node is a fwd declare you should inspect the fwd node id. -// If a node isn't a fwd declare but has a backward id, the node should be ignored during traversal. -// (That node can be defined in a different namespace or type while it's declared elsewhere). +// Note: Regarding nodes, node 0 is the root node (global scope) +// If a node is a fwd declare you should inspect the fwd node id. +// If a node isn't a fwd declare but has a backward id, the node should be +// ignored during traversal. (That node can be defined in a different +// namespace or type while it's declared elsewhere). struct ReflectionData { D3D12_HLSL_REFLECTION_FEATURE Features{}; diff --git a/include/dxc/dxcreflect.h b/include/dxc/dxcreflect.h index 2104c7d0d4..e90e417316 100644 --- a/include/dxc/dxcreflect.h +++ b/include/dxc/dxcreflect.h @@ -13,16 +13,16 @@ #define __DXC_REFLECT__ #ifndef _WIN32 - #include "dxc/WinAdapter.h" - // need to disable this as it is voilated by this header - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" - // Need to instruct non-windows compilers on what an interface is - #define interface struct +#include "dxc/WinAdapter.h" +// need to disable this as it is voilated by this header +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +// Need to instruct non-windows compilers on what an interface is +#define interface struct #endif -#include "dxc/dxcapi.h" #include "d3d12shader.h" +#include "dxc/dxcapi.h" #ifdef _MSC_VER #define CLSID_SCOPE __declspec(selectany) extern @@ -35,7 +35,7 @@ // This is useful to avoid custom parsers from reinventing the wheel. // You could use it to find all entrypoints even if [shader("")] isn't used, // Find struct/enum information, find out about optimized out registers, etc. -// This is a limited AST that doesn't include anything beyond symbols +// This is a limited AST that doesn't include anything beyond symbols // (so no details about instructions). enum D3D12_HLSL_REFLECTION_FEATURE { @@ -57,23 +57,23 @@ enum D3D12_HLSL_REFLECTION_FEATURE { // Symbol info (stripping this will remove names and file location info) D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO = 1 << 16, - D3D12_HLSL_REFLECTION_FEATURE_ALL = D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - 1 + D3D12_HLSL_REFLECTION_FEATURE_ALL = + D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO - 1 }; -inline D3D12_HLSL_REFLECTION_FEATURE &operator|=(D3D12_HLSL_REFLECTION_FEATURE &a, - D3D12_HLSL_REFLECTION_FEATURE b) { +inline D3D12_HLSL_REFLECTION_FEATURE & +operator|=(D3D12_HLSL_REFLECTION_FEATURE &a, D3D12_HLSL_REFLECTION_FEATURE b) { return a = (D3D12_HLSL_REFLECTION_FEATURE)(uint32_t(a) | uint32_t(b)); } inline D3D12_HLSL_REFLECTION_FEATURE & -operator&=(D3D12_HLSL_REFLECTION_FEATURE &a, - D3D12_HLSL_REFLECTION_FEATURE b) { +operator&=(D3D12_HLSL_REFLECTION_FEATURE &a, D3D12_HLSL_REFLECTION_FEATURE b) { return a = (D3D12_HLSL_REFLECTION_FEATURE)(uint32_t(a) & uint32_t(b)); } inline D3D12_HLSL_REFLECTION_FEATURE operator~(D3D12_HLSL_REFLECTION_FEATURE a) { - return (D3D12_HLSL_REFLECTION_FEATURE) ~uint32_t(a); + return (D3D12_HLSL_REFLECTION_FEATURE)~uint32_t(a); } struct D3D12_HLSL_REFLECTION_DESC { @@ -90,15 +90,15 @@ struct D3D12_HLSL_REFLECTION_DESC { }; struct D3D12_HLSL_FUNCTION_DESC { - LPCSTR Name; // Function name - UINT FunctionParameterCount; // Number of logical parameters in the function - // signature (not including return) - BOOL HasReturn; // TRUE, if function returns a value, false - it is a - // subroutine + LPCSTR Name; // Function name + UINT FunctionParameterCount; // Number of logical parameters in the function + // signature (not including return) + BOOL HasReturn; // TRUE, if function returns a value, false - it is a + // subroutine }; enum D3D12_HLSL_ENUM_TYPE { - + D3D12_HLSL_ENUM_TYPE_UINT, D3D12_HLSL_ENUM_TYPE_INT, D3D12_HLSL_ENUM_TYPE_UINT64_T, @@ -177,7 +177,7 @@ struct D3D12_HLSL_NODE { UINT ChildCount; UINT Parent; UINT AnnotationCount; - UINT FwdBckDeclareNode; //If UINT_MAX has no forward / backward declare + UINT FwdBckDeclareNode; // If UINT_MAX has no forward / backward declare BOOL IsFwdDeclare; }; @@ -206,9 +206,10 @@ typedef struct _D3D12_SHADER_TYPE_DESC1 { } D3D12_SHADER_TYPE_DESC1; DECLARE_INTERFACE_(ID3D12ShaderReflectionType1, ID3D12ShaderReflectionType) { - STDMETHOD(GetDesc1)(THIS_ _Out_ D3D12_SHADER_TYPE_DESC1 *pDesc) PURE; - STDMETHOD(GetArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) PURE; - STDMETHOD(GetDisplayArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) PURE; + STDMETHOD(GetDesc1)(THIS_ _Out_ D3D12_SHADER_TYPE_DESC1 * pDesc) PURE; + STDMETHOD(GetArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC * pArrayDesc) PURE; + STDMETHOD(GetDisplayArrayDesc) + (THIS_ _Out_ D3D12_ARRAY_DESC * pArrayDesc) PURE; }; typedef interface IDxcHLSLReflection IDxcHLSLReflection; @@ -216,30 +217,30 @@ typedef interface IDxcHLSLReflection IDxcHLSLReflection; // {7016F834-AE85-4C86-A473-8C2C981DD370} interface DECLSPEC_UUID("7016f834-ae85-4c86-a473-8c2c981dd370") IDxcHLSLReflection; -DEFINE_GUID(IID_IDxcHLSLReflection, 0x7016f834, 0xae85, 0x4c86, 0xa4, 0x73, 0x8c, - 0x2c, 0x98, 0x1d, 0xd3, 0x70); +DEFINE_GUID(IID_IDxcHLSLReflection, 0x7016f834, 0xae85, 0x4c86, 0xa4, 0x73, + 0x8c, 0x2c, 0x98, 0x1d, 0xd3, 0x70); #undef INTERFACE #define INTERFACE IDxcHLSLReflection DECLARE_INTERFACE(IDxcHLSLReflection) { - STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_HLSL_REFLECTION_DESC *pDesc) PURE; + STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_HLSL_REFLECTION_DESC * pDesc) PURE; STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex) (THIS_ _In_ UINT Index) PURE; // The D3D12_SHADER_INPUT_BIND_DESC permits providing invalid Space and // BindPoint. In the future, implementations could decide to return this - // depending on the backend. But since this is HLSL frontend reflection, we don't - // know the bindings on the backend. + // depending on the backend. But since this is HLSL frontend reflection, we + // don't know the bindings on the backend. STDMETHOD(GetResourceBindingDesc) - (THIS_ _In_ UINT ResourceIndex, _Out_ D3D12_SHADER_INPUT_BIND_DESC1 *pDesc) + (THIS_ _In_ UINT ResourceIndex, _Out_ D3D12_SHADER_INPUT_BIND_DESC1 * pDesc) PURE; STDMETHOD(GetFunctionDesc) - (THIS_ _In_ UINT FunctionIndex, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) + (THIS_ _In_ UINT FunctionIndex, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC * pDesc) PURE; // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value. @@ -247,87 +248,83 @@ DECLARE_INTERFACE(IDxcHLSLReflection) { (THIS_ _In_ UINT FunctionIndex, THIS_ _In_ INT ParameterIndex) PURE; STDMETHOD(GetStructTypeByIndex) - (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) - PURE; + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType * *ppType) PURE; STDMETHOD(GetUnionTypeByIndex) - (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) - PURE; + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType * *ppType) PURE; STDMETHOD(GetInterfaceTypeByIndex) - (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) - PURE; + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType * *ppType) PURE; STDMETHOD(GetTypeByIndex) - (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType **ppType) - PURE; + (THIS_ _In_ UINT Index, _Outptr_ ID3D12ShaderReflectionType * *ppType) PURE; STDMETHOD(GetEnumDesc) - (THIS_ _In_ UINT EnumIndex, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; + (THIS_ _In_ UINT EnumIndex, _Out_ D3D12_HLSL_ENUM_DESC * pDesc) PURE; STDMETHOD(GetEnumValueByIndex) (THIS_ _In_ UINT EnumIndex, _In_ UINT ValueIndex, - _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) PURE; + _Out_ D3D12_HLSL_ENUM_VALUE * pValueDesc) PURE; STDMETHOD(GetAnnotationByIndex) (THIS_ _In_ UINT NodeId, _In_ UINT Index, - _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) PURE; + _Out_ D3D12_HLSL_ANNOTATION * pAnnotation) PURE; STDMETHOD(GetNodeDesc) - (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE *pDesc) PURE; + (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE * pDesc) PURE; STDMETHOD(GetChildNode) - (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, - _Out_ UINT *pChildNodeId) PURE; + (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, _Out_ UINT * pChildNodeId) + PURE; STDMETHOD(GetChildDesc) (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, - _Out_ D3D12_HLSL_NODE *pDesc) PURE; + _Out_ D3D12_HLSL_NODE * pDesc) PURE; // Only available if symbols aren't stripped STDMETHOD(GetNodeSymbolDesc) - (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE_SYMBOL *pSymbol) PURE; + (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE_SYMBOL * pSymbol) PURE; // Name helpers STDMETHOD(GetNodeByName) - (THIS_ _In_ LPCSTR Name, _Out_ UINT *pNodeId) PURE; + (THIS_ _In_ LPCSTR Name, _Out_ UINT * pNodeId) PURE; STDMETHOD(GetNodeSymbolDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE_SYMBOL *pSymbol) PURE; + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE_SYMBOL * pSymbol) PURE; STDMETHOD(GetNodeDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE *pDesc) PURE; + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE * pDesc) PURE; STDMETHOD(GetAnnotationByIndexAndName) (THIS_ _In_ LPCSTR Name, _In_ UINT Index, - _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) PURE; + _Out_ D3D12_HLSL_ANNOTATION * pAnnotation) PURE; STDMETHOD(GetEnumDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) PURE; + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_ENUM_DESC * pDesc) PURE; STDMETHOD(GetEnumValueByNameAndIndex) (THIS_ _In_ LPCSTR Name, _In_ UINT ValueIndex, - _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) PURE; + _Out_ D3D12_HLSL_ENUM_VALUE * pValueDesc) PURE; STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByName) (THIS_ _In_ LPCSTR Name) PURE; STDMETHOD(GetFunctionDescByName) - (THIS_ _In_ LPCSTR Name, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) PURE; + (THIS_ _In_ LPCSTR Name, THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC * pDesc) PURE; STDMETHOD(GetResourceBindingDescByName) (THIS_ _In_ LPCSTR Name, _Out_ D3D12_SHADER_INPUT_BIND_DESC1 * pDesc) PURE; STDMETHOD(GetStructTypeByName) - (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType * *ppType) PURE; STDMETHOD(GetUnionTypeByName) - (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType * *ppType) PURE; STDMETHOD(GetInterfaceTypeByName) - (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType **ppType) PURE; + (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType * *ppType) PURE; }; #undef INTERFACE @@ -351,8 +348,7 @@ struct IDxcHLSLReflector : public IUnknown { // Defines DxcDefine *pDefines, UINT32 defineCount, // user-provided interface to handle #include directives (optional) - IDxcIncludeHandler *pIncludeHandler, - IDxcOperationResult **ppResult) = 0; + IDxcIncludeHandler *pIncludeHandler, IDxcOperationResult **ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE FromBlob(IDxcBlob *data, IDxcHLSLReflection **ppReflection) = 0; diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index ea753e6520..d174720f0b 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -991,7 +991,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, // XXX TODO: Sort this out, since it's required for new API, but a separate // argument for old APIs. if ((flagsToInclude & hlsl::options::DriverOption) && - !(flagsToInclude & (hlsl::options::RewriteOption | hlsl::options::ReflectOption)) && + !(flagsToInclude & + (hlsl::options::RewriteOption | hlsl::options::ReflectOption)) && opts.TargetProfile.empty() && !opts.DumpBin && opts.Preprocess.empty() && !opts.RecompileFromBinary) { // Target profile is required in arguments only for drivers when compiling; diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 7017e6708e..07146bfee0 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -51,12 +51,10 @@ using namespace hlsl; namespace hlsl { -[[nodiscard]] ReflectionError DxcHLSLReflectionDataFromAST(ReflectionData &Result, - clang::CompilerInstance &Compiler, - clang::TranslationUnitDecl &Ctx, - uint32_t AutoBindingSpace, - D3D12_HLSL_REFLECTION_FEATURE Features, - bool DefaultRowMaj); +[[nodiscard]] ReflectionError DxcHLSLReflectionDataFromAST( + ReflectionData &Result, clang::CompilerInstance &Compiler, + clang::TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, + D3D12_HLSL_REFLECTION_FEATURE Features, bool DefaultRowMaj); } struct ASTHelper { @@ -142,9 +140,7 @@ class CHLSLInvalidSRConstantBuffer final } STDMETHOD_(ID3D12ShaderReflectionVariable *, GetVariableByIndex) - (UINT Index) override { - return &g_InvalidSRVariable; - } + (UINT Index) override { return &g_InvalidSRVariable; } STDMETHOD_(ID3D12ShaderReflectionVariable *, GetVariableByName) (LPCSTR Name) override { return &g_InvalidSRVariable; } @@ -161,7 +157,6 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { friend class CHLSLReflectionConstantBuffer; protected: - std::string m_NameUnderlying; std::string m_NameDisplay; std::vector m_MemberNames; @@ -177,8 +172,8 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { D3D12_ARRAY_DESC m_ArrayDescUnderlying; D3D12_ARRAY_DESC m_ArrayDescDisplay; - void InitializeArray(const ReflectionData &Data, - D3D12_ARRAY_DESC &desc, uint32_t &elements, + void InitializeArray(const ReflectionData &Data, D3D12_ARRAY_DESC &desc, + uint32_t &elements, const ReflectionArrayOrElements &arrElem) { if (arrElem.IsArray()) { @@ -207,7 +202,6 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { } public: - STDMETHOD(IsEqual)(ID3D12ShaderReflectionType *pType) override { return (this == pType) ? S_OK : S_FALSE; } @@ -232,7 +226,8 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { return S_OK; } - STDMETHOD(GetDisplayArrayDesc)(THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) override { + STDMETHOD(GetDisplayArrayDesc) + (THIS_ _Out_ D3D12_ARRAY_DESC *pArrayDesc) override { if (!pArrayDesc) return E_POINTER; @@ -264,7 +259,8 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { ReflectionVariableTypeSymbol sym = Data.TypeSymbols[TypeId]; m_NameUnderlying = Data.Strings[sym.UnderlyingNameId]; m_NameDisplay = Data.Strings[sym.DisplayNameId]; - InitializeArray(Data, m_ArrayDescDisplay, m_ElementsDisplay, sym.DisplayArray); + InitializeArray(Data, m_ArrayDescDisplay, m_ElementsDisplay, + sym.DisplayArray); } uint32_t memberCount = type.GetMemberCount(); @@ -307,18 +303,17 @@ class CHLSLReflectionType final : public ID3D12ShaderReflectionType1 { const ReflectionVariableType &type = m_Data->Types[m_TypeId]; - *pDesc = D3D12_SHADER_TYPE_DESC { + *pDesc = D3D12_SHADER_TYPE_DESC{ - type.GetClass(), - type.GetType(), - type.GetRows(), - type.GetColumns(), + type.GetClass(), + type.GetType(), + type.GetRows(), + type.GetColumns(), - m_ElementsUnderlying, - uint32_t(m_MemberTypes.size()), - 0, //TODO: Offset if we have one - m_NameUnderlying.c_str() - }; + m_ElementsUnderlying, + uint32_t(m_MemberTypes.size()), + 0, // TODO: Offset if we have one + m_NameUnderlying.c_str()}; return S_OK; } @@ -424,7 +419,8 @@ class CHLSLFunctionParameter final : public ID3D12FunctionParameterReflection { ? m_Data->Strings[m_Data->NodeSymbols[m_NodeId].GetNameId()].c_str() : ""; - const ReflectionFunctionParameter ¶m = m_Data->Parameters[node.GetLocalId()]; + const ReflectionFunctionParameter ¶m = + m_Data->Parameters[node.GetLocalId()]; const ReflectionVariableType &type = m_Data->Types[param.TypeId]; *pDesc = @@ -569,9 +565,9 @@ class CHLSLReflectionConstantBuffer final //$Globals (only if the global scope contains any VARIABLE node) void InitializeGlobals(const ReflectionData &Data, - const std::vector &Globals, - CHLSLReflectionConstantBuffer *ConstantBuffer, - std::vector &Types) { + const std::vector &Globals, + CHLSLReflectionConstantBuffer *ConstantBuffer, + std::vector &Types) { m_ReflectionName = "$Globals"; @@ -655,14 +651,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { std::vector Types; - enum class FwdDeclType { - STRUCT, - UNION, - ENUM, - FUNCTION, - INTERFACE, - COUNT - }; + enum class FwdDeclType { STRUCT, UNION, ENUM, FUNCTION, INTERFACE, COUNT }; std::vector NonFwdIds[int(FwdDeclType::COUNT)]; @@ -702,7 +691,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { functionParameters.push_back(i); } - // Filter out fwd declarations for structs, unions, interfaces, functions, enums + // Filter out fwd declarations for structs, unions, interfaces, functions, + // enums if (!node.IsFwdDeclare()) { @@ -792,9 +782,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { Data, globalVars, &ConstantBuffers[Data.Buffers.size()], Types); } - DxcHLSLReflection(ReflectionData &&moved) : Data(moved) { - Finalize(); - } + DxcHLSLReflection(ReflectionData &&moved) : Data(moved) { Finalize(); } DxcHLSLReflection &operator=(DxcHLSLReflection &&moved) { @@ -816,7 +804,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { return *this; } - //Conversion of DxcHLSL structs to D3D12_HLSL standardized structs + // Conversion of DxcHLSL structs to D3D12_HLSL standardized structs STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_HLSL_REFLECTION_DESC *pDesc) override { @@ -878,17 +866,16 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { // want to change it reg.GetBindCount(), - reg.GetFlags(), reg.GetReturnType(), - reg.GetDimension(), + reg.GetFlags(), reg.GetReturnType(), reg.GetDimension(), uint32_t(-1), // Also no valid data depending on backend uint32_t(-1), // Invalid space (see bindPoint ^) reg.GetNodeId()}; return S_OK; } - + STDMETHOD(GetEnumDesc) - (THIS_ _In_ UINT EnumIndex, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) override { + (THIS_ _In_ UINT EnumIndex, _Out_ D3D12_HLSL_ENUM_DESC *pDesc) override { IFR(ZeroMemoryToOut(pDesc)); @@ -902,7 +889,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO ? Data.Strings[Data.NodeSymbols[enm.NodeId].GetNameId()].c_str() : ""; - + *pDesc = D3D12_HLSL_ENUM_DESC{ name, uint32_t(Data.Nodes[enm.NodeId].GetChildCount()), enm.Type}; @@ -910,15 +897,16 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD(GetEnumValueByIndex) - (THIS_ _In_ UINT EnumIndex, _In_ UINT ValueIndex, - _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) override { + (THIS_ _In_ UINT EnumIndex, _In_ UINT ValueIndex, + _Out_ D3D12_HLSL_ENUM_VALUE *pValueDesc) override { IFR(ZeroMemoryToOut(pValueDesc)); if (EnumIndex >= NonFwdIds[int(FwdDeclType::ENUM)].size()) return E_INVALIDARG; - const ReflectionEnumeration &enm = Data.Enums[NonFwdIds[int(FwdDeclType::ENUM)][EnumIndex]]; + const ReflectionEnumeration &enm = + Data.Enums[NonFwdIds[int(FwdDeclType::ENUM)][EnumIndex]]; const ReflectionNode &parent = Data.Nodes[enm.NodeId]; if (ValueIndex >= parent.GetChildCount()) @@ -986,32 +974,33 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD(GetNodeDesc) - (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE *pDesc) override { + (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE *pDesc) override { IFR(ZeroMemoryToOut(pDesc)); if (NodeId >= Data.Nodes.size()) return E_INVALIDARG; - LPCSTR name = Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO + LPCSTR name = + Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO ? Data.Strings[Data.NodeSymbols[NodeId].GetNameId()].c_str() - : ""; + : ""; const ReflectionNode &node = Data.Nodes[NodeId]; uint32_t localId = node.GetLocalId(); uint32_t parentId = node.GetParentId(); - //Real local id is at definition + // Real local id is at definition if (node.IsFwdDeclare()) { if (node.IsFwdBckDefined()) localId = Data.Nodes[node.GetFwdBck()].GetLocalId(); } - //Real parent is at declaration + // Real parent is at declaration - else if(node.IsFwdBckDefined()) + else if (node.IsFwdBckDefined()) parentId = Data.Nodes[node.GetFwdBck()].GetParentId(); LPCSTR semantic = ""; @@ -1034,8 +1023,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD(GetChildNode) - (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, - _Out_ UINT *pChildNodeId) override { + (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, + _Out_ UINT *pChildNodeId) override { IFR(ZeroMemoryToOut(pChildNodeId)); @@ -1052,8 +1041,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD(GetChildDesc) - (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, - _Out_ D3D12_HLSL_NODE *pDesc) override { + (THIS_ _In_ UINT NodeId, THIS_ _In_ UINT ChildId, + _Out_ D3D12_HLSL_NODE *pDesc) override { IFR(ZeroMemoryToOut(pDesc)); @@ -1151,7 +1140,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { *ppType = &Types[NonFwdIds[int(FwdDeclType::INTERFACE)][Index]]; return S_OK; } - + STDMETHOD(GetNodeSymbolDesc) (THIS_ _In_ UINT NodeId, _Out_ D3D12_HLSL_NODE_SYMBOL *pDesc) override { @@ -1173,10 +1162,10 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { return S_OK; } - //Helper for conversion between symbol names + // Helper for conversion between symbol names STDMETHOD(GetNodeByName) - (THIS_ _In_ LPCSTR Name, _Out_ UINT *pNodeId) override { + (THIS_ _In_ LPCSTR Name, _Out_ UINT *pNodeId) override { if (!Name || !pNodeId) return E_POINTER; @@ -1204,7 +1193,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD(GetNodeSymbolDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE_SYMBOL *pDesc) override { + (THIS_ _In_ LPCSTR Name, _Out_ D3D12_HLSL_NODE_SYMBOL *pDesc) override { IFR(ZeroMemoryToOut(pDesc)); @@ -1215,7 +1204,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD(GetResourceBindingDescByName) - (THIS_ _In_ LPCSTR Name, _Out_ D3D12_SHADER_INPUT_BIND_DESC1 *pDesc) override { + (THIS_ _In_ LPCSTR Name, + _Out_ D3D12_SHADER_INPUT_BIND_DESC1 *pDesc) override { IFR(ZeroMemoryToOut(pDesc)); @@ -1270,8 +1260,8 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { } STDMETHOD(GetAnnotationByIndexAndName) - (THIS_ _In_ LPCSTR Name, _In_ UINT Index, - _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) override { + (THIS_ _In_ LPCSTR Name, _In_ UINT Index, + _Out_ D3D12_HLSL_ANNOTATION *pAnnotation) override { IFR(ZeroMemoryToOut(pAnnotation)); @@ -1283,7 +1273,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { STDMETHOD(GetFunctionDescByName) (THIS_ _In_ LPCSTR Name, - THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) override{ + THIS_ _Out_ D3D12_HLSL_FUNCTION_DESC *pDesc) override { IFR(ZeroMemoryToOut(pDesc)); @@ -1464,12 +1454,10 @@ void SetupCompilerCommon(CompilerInstance &compiler, } } -void SetupCompiler(CompilerInstance &compiler, - DxcLangExtensionsHelper *helper, LPCSTR pMainFile, - TextDiagnosticPrinter *diagPrinter, - ASTUnit::RemappedFile *rewrite, - hlsl::options::DxcOpts &opts, LPCSTR pDefines, - dxcutil::DxcArgsFileSystem *msfPtr) { +void SetupCompiler(CompilerInstance &compiler, DxcLangExtensionsHelper *helper, + LPCSTR pMainFile, TextDiagnosticPrinter *diagPrinter, + ASTUnit::RemappedFile *rewrite, hlsl::options::DxcOpts &opts, + LPCSTR pDefines, dxcutil::DxcArgsFileSystem *msfPtr) { SetupCompilerCommon(compiler, helper, pMainFile, diagPrinter, rewrite, opts); @@ -1521,9 +1509,8 @@ HRESULT GenerateAST(DxcLangExtensionsHelper *pExtHelper, LPCSTR pFileName, &compiler.getDiagnosticOpts()); std::string definesStr = DefinesToString(pDefines, defineCount); - SetupCompiler( - compiler, pExtHelper, pFileName, diagPrinter.get(), pRemap, opts, - defineCount > 0 ? definesStr.c_str() : nullptr, msfPtr); + SetupCompiler(compiler, pExtHelper, pFileName, diagPrinter.get(), pRemap, + opts, defineCount > 0 ? definesStr.c_str() : nullptr, msfPtr); // Parse the source file. compiler.getDiagnosticClient().BeginSourceFile(compiler.getLangOpts(), @@ -1545,20 +1532,19 @@ HRESULT GenerateAST(DxcLangExtensionsHelper *pExtHelper, LPCSTR pFileName, } HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, - ASTUnit::RemappedFile *pRemap, - hlsl::options::DxcOpts &opts, DxcDefine *pDefines, - UINT32 defineCount, std::string &warnings, - std::string &result, - dxcutil::DxcArgsFileSystem *msfPtr, - ReflectionData &reflection) { + ASTUnit::RemappedFile *pRemap, + hlsl::options::DxcOpts &opts, DxcDefine *pDefines, + UINT32 defineCount, std::string &warnings, + std::string &result, dxcutil::DxcArgsFileSystem *msfPtr, + ReflectionData &reflection) { raw_string_ostream o(result); raw_string_ostream w(warnings); ASTHelper astHelper; - HRESULT hr = GenerateAST(pHelper, pFileName, pRemap, pDefines, defineCount, astHelper, - opts, msfPtr, w); + HRESULT hr = GenerateAST(pHelper, pFileName, pRemap, pDefines, defineCount, + astHelper, opts, msfPtr, w); if (FAILED(hr)) return hr; @@ -1591,11 +1577,12 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, reflectMask |= D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; ReflectionData refl; - + if (ReflectionError err = DxcHLSLReflectionDataFromAST( refl, astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, reflectMask, opts.DefaultRowMajor)) { - fprintf(stderr, "DxcHLSLReflectionDataFromAST failed %s\n", err.toString().c_str()); + fprintf(stderr, "DxcHLSLReflectionDataFromAST failed %s\n", + err.toString().c_str()); return E_FAIL; } @@ -1606,44 +1593,44 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, // Debug: Verify deserialization, otherwise print error. - #ifndef NDEBUG +#ifndef NDEBUG - std::vector bytes; - refl.Dump(bytes); + std::vector bytes; + refl.Dump(bytes); - ReflectionData deserialized; + ReflectionData deserialized; - if (ReflectionError err = deserialized.Deserialize(bytes, true)) { - fprintf(stderr, "Deserialize failed %s\n", err.toString().c_str()); - return E_FAIL; - } + if (ReflectionError err = deserialized.Deserialize(bytes, true)) { + fprintf(stderr, "Deserialize failed %s\n", err.toString().c_str()); + return E_FAIL; + } - if (!(deserialized == refl)) { - fprintf(stderr, "Dump or Deserialize doesn't match\n"); - return E_FAIL; - } + if (!(deserialized == refl)) { + fprintf(stderr, "Dump or Deserialize doesn't match\n"); + return E_FAIL; + } - // Test stripping symbols + // Test stripping symbols - if (!opts.ReflOpt.DisableSymbols) { + if (!opts.ReflOpt.DisableSymbols) { - deserialized.StripSymbols(); - deserialized.Dump(bytes); + deserialized.StripSymbols(); + deserialized.Dump(bytes); - ReflectionData deserialized2; + ReflectionData deserialized2; - if (ReflectionError err = deserialized2.Deserialize(bytes, true)) { - fprintf(stderr, "Deserialize failed %s\n", err.toString().c_str()); - return E_FAIL; - } + if (ReflectionError err = deserialized2.Deserialize(bytes, true)) { + fprintf(stderr, "Deserialize failed %s\n", err.toString().c_str()); + return E_FAIL; + } - if (!(deserialized2 == deserialized)) { - fprintf(stderr, "Dump or Deserialize doesn't match\n"); - return E_FAIL; - } + if (!(deserialized2 == deserialized)) { + fprintf(stderr, "Dump or Deserialize doesn't match\n"); + return E_FAIL; } + } - #endif +#endif reflection = std::move(refl); @@ -1655,8 +1642,8 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, } HRESULT ReadOptsAndValidate(hlsl::options::MainArgs &mainArgs, - hlsl::options::DxcOpts &opts, - IDxcOperationResult **ppResult) { + hlsl::options::DxcOpts &opts, + IDxcOperationResult **ppResult) { const llvm::opt::OptTable *table = ::options::getHlslOptTable(); CComPtr pOutputStream; @@ -1773,8 +1760,9 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { CATCH_CPP_RETURN_HRESULT(); } - HRESULT STDMETHODCALLTYPE FromBlob(IDxcBlob *data, IDxcHLSLReflection **ppReflection) override { - + HRESULT STDMETHODCALLTYPE + FromBlob(IDxcBlob *data, IDxcHLSLReflection **ppReflection) override { + if (!data || !data->GetBufferSize() || !ppReflection) return E_POINTER; @@ -1796,7 +1784,7 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { } HRESULT STDMETHODCALLTYPE ToBlob(IDxcHLSLReflection *reflection, - IDxcBlob **ppResult) override { + IDxcBlob **ppResult) override { if (!reflection || !ppResult) return E_POINTER; diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index 7288d879e7..f640bf7d39 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -15,7 +15,7 @@ #undef max namespace hlsl { - + [[nodiscard]] ReflectionError ReflectionData::RegisterString(uint32_t &StringId, const std::string &Name, bool IsNonDebug) { @@ -63,7 +63,7 @@ ReflectionData::RegisterString(uint32_t &StringId, const std::string &Name, [[nodiscard]] ReflectionError ReflectionData::PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, - const std::vector &ArraySize) { + const std::vector &ArraySize) { if (ArraySizeFlat <= 1 || ArraySize.size() <= 1) { ArrayId = uint32_t(-1); @@ -111,8 +111,8 @@ ReflectionData::PushArray(uint32_t &ArrayId, uint32_t ArraySizeFlat, } [[nodiscard]] ReflectionError -ReflectionData::RegisterTypeList( - const std::vector &TypeIds, uint32_t &Offset, uint8_t &Len) { +ReflectionData::RegisterTypeList(const std::vector &TypeIds, + uint32_t &Offset, uint8_t &Len) { if (TypeIds.empty()) return ReflectionErrorSuccess; @@ -209,13 +209,11 @@ const T &UnsafeCast(const std::vector &Bytes, uint64_t Offset) { return *(const T *)(Bytes.data() + Offset); } -template -void SkipPadding(uint64_t &Offset) { +template void SkipPadding(uint64_t &Offset) { Offset = (Offset + alignof(T) - 1) / alignof(T) * alignof(T); } -template -void Skip(uint64_t &Offset, const std::vector &Vec) { +template void Skip(uint64_t &Offset, const std::vector &Vec) { Offset += Vec.size() * sizeof(T); } @@ -234,13 +232,14 @@ void Advance(uint64_t &Offset, } } -template -void Advance(uint64_t& Offset, const std::vector& Vec, const std::vector& Vec2, args... arg) { +template +void Advance(uint64_t &Offset, const std::vector &Vec, + const std::vector &Vec2, args... arg) { Advance(Offset, Vec); Advance(Offset, Vec2, arg...); } -template +template void Append(std::vector &Bytes, uint64_t &Offset, const std::vector &Vec) { static_assert(std::is_pod_v, "Append only works on POD types"); @@ -270,7 +269,7 @@ void Append(std::vector &Bytes, uint64_t &Offset, } } -template +template void Append(std::vector &Bytes, uint64_t &Offset, const std::vector &Vec, const std::vector &Vec2, args... arg) { @@ -279,7 +278,8 @@ void Append(std::vector &Bytes, uint64_t &Offset, } template >> -[[nodiscard]] ReflectionError Consume(const std::vector &Bytes, uint64_t &Offset, T &t) { +[[nodiscard]] ReflectionError Consume(const std::vector &Bytes, + uint64_t &Offset, T &t) { static_assert(std::is_pod_v, "Consume only works on POD types"); @@ -296,8 +296,8 @@ template >> template [[nodiscard]] ReflectionError Consume(const std::vector &Bytes, - uint64_t &Offset, T *target, - uint64_t Len) { + uint64_t &Offset, T *target, + uint64_t Len) { static_assert(std::is_pod_v, "Consume only works on POD types"); @@ -314,8 +314,8 @@ template template [[nodiscard]] ReflectionError Consume(const std::vector &Bytes, - uint64_t &Offset, std::vector &Vec, - uint64_t Len) { + uint64_t &Offset, std::vector &Vec, + uint64_t Len) { Vec.resize(Len); return Consume(Bytes, Offset, Vec.data(), Len); } @@ -323,47 +323,47 @@ template template <> [[nodiscard]] ReflectionError Consume(const std::vector &Bytes, uint64_t &Offset, - std::vector &Vec, uint64_t Len) { + std::vector &Vec, uint64_t Len) { Vec.resize(Len); for (uint64_t i = 0; i < Len; ++i) { - if (Offset >= Bytes.size()) + if (Offset >= Bytes.size()) return HLSL_REFL_ERR("Couldn't consume string len; out of bounds!"); - - uint16_t ourLen = uint8_t(Bytes.at(Offset++)); - if (ourLen >> 7) { + uint16_t ourLen = uint8_t(Bytes.at(Offset++)); - if (Offset >= Bytes.size()) + if (ourLen >> 7) { + + if (Offset >= Bytes.size()) return HLSL_REFL_ERR("Couldn't consume string len; out of bounds!"); - ourLen &= ~(1 << 7); - ourLen |= uint16_t(Bytes.at(Offset++)) << 7; - } + ourLen &= ~(1 << 7); + ourLen |= uint16_t(Bytes.at(Offset++)) << 7; + } - if (Offset + ourLen > Bytes.size()) - return HLSL_REFL_ERR("Couldn't consume string len; out of bounds!"); + if (Offset + ourLen > Bytes.size()) + return HLSL_REFL_ERR("Couldn't consume string len; out of bounds!"); - Vec[i].resize(ourLen); - std::memcpy(Vec[i].data(), Bytes.data() + Offset, ourLen); - Offset += ourLen; + Vec[i].resize(ourLen); + std::memcpy(Vec[i].data(), Bytes.data() + Offset, ourLen); + Offset += ourLen; } return ReflectionErrorSuccess; } -template +template [[nodiscard]] ReflectionError Consume(const std::vector &Bytes, - uint64_t &Offset, - std::vector &Vec, uint64_t Len, std::vector &Vec2, - uint64_t Len2, args&... arg) { + uint64_t &Offset, std::vector &Vec, + uint64_t Len, std::vector &Vec2, + uint64_t Len2, args &...arg) { if (ReflectionError err = Consume(Bytes, Offset, Vec, Len)) - return err; + return err; if (ReflectionError err = Consume(Bytes, Offset, Vec2, Len2, arg...)) - return err; + return err; return ReflectionErrorSuccess; } @@ -391,17 +391,17 @@ void RecurseNameGenerationType(ReflectionData &Refl, uint32_t TypeId, const ReflectionVariableType &type = Refl.Types[TypeId]; if (type.GetClass() == D3D_SVC_STRUCT) - for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { - uint32_t memberId = i + type.GetMemberStart(); - std::string memberName = - Parent + "." + Refl.Strings[Refl.MemberNameIds[memberId]]; + uint32_t memberId = i + type.GetMemberStart(); + std::string memberName = + Parent + "." + Refl.Strings[Refl.MemberNameIds[memberId]]; - Refl.FullyResolvedToMemberId[memberName] = memberId; + Refl.FullyResolvedToMemberId[memberName] = memberId; - RecurseNameGenerationType(Refl, Refl.MemberTypeIds[memberId], i, - memberName); - } + RecurseNameGenerationType(Refl, Refl.MemberTypeIds[memberId], i, + memberName); + } } uint32_t RecurseNameGeneration(ReflectionData &Refl, uint32_t NodeId, @@ -411,14 +411,14 @@ uint32_t RecurseNameGeneration(ReflectionData &Refl, uint32_t NodeId, ReflectionNode node = Refl.Nodes[NodeId]; if (node.IsFwdDeclare() && node.IsFwdBckDefined()) { - NodeId = node.GetFwdBck(); - node = Refl.Nodes[NodeId]; + NodeId = node.GetFwdBck(); + node = Refl.Nodes[NodeId]; } std::string self = Refl.Strings[Refl.NodeSymbols[NodeId].GetNameId()]; if (self.empty() && NodeId) - self = std::to_string(LocalId); + self = std::to_string(LocalId); self = Parent.empty() ? self : Parent + (IsDot ? "." : "::") + self; Refl.FullyResolvedToNodeId[self] = NodeId; @@ -431,25 +431,25 @@ uint32_t RecurseNameGeneration(ReflectionData &Refl, uint32_t NodeId, node.GetNodeType() == D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE; for (uint32_t i = 0, j = 0; i < node.GetChildCount(); ++i, ++j) - i += RecurseNameGeneration(Refl, NodeId + 1 + i, j, self, isDotChild); + i += RecurseNameGeneration(Refl, NodeId + 1 + i, j, self, isDotChild); if (isVar) { - uint32_t typeId = node.GetLocalId(); - const ReflectionVariableType &type = Refl.Types[typeId]; + uint32_t typeId = node.GetLocalId(); + const ReflectionVariableType &type = Refl.Types[typeId]; - if (type.GetClass() == D3D_SVC_STRUCT) - for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { + if (type.GetClass() == D3D_SVC_STRUCT) + for (uint32_t i = 0; i < type.GetMemberCount(); ++i) { - uint32_t memberId = i + type.GetMemberStart(); - std::string memberName = - self + "." + Refl.Strings[Refl.MemberNameIds[memberId]]; + uint32_t memberId = i + type.GetMemberStart(); + std::string memberName = + self + "." + Refl.Strings[Refl.MemberNameIds[memberId]]; - Refl.FullyResolvedToMemberId[memberName] = memberId; + Refl.FullyResolvedToMemberId[memberName] = memberId; - RecurseNameGenerationType(Refl, Refl.MemberTypeIds[memberId], i, - memberName); - } + RecurseNameGenerationType(Refl, Refl.MemberTypeIds[memberId], i, + memberName); + } } return node.GetChildCount(); @@ -458,7 +458,7 @@ uint32_t RecurseNameGeneration(ReflectionData &Refl, uint32_t NodeId, bool ReflectionData::GenerateNameLookupTable() { if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) || Nodes.empty()) - return false; + return false; NodeIdToFullyResolved.resize(Nodes.size()); RecurseNameGeneration(*this, 0, 0, "", false); @@ -478,17 +478,27 @@ void ReflectionData::Dump(std::vector &Bytes) const { toReserve = 0; - UnsafeCast(Bytes, toReserve) = { - ReflectionDataMagic, ReflectionDataVersion, - uint16_t(Sources.size()), Features, - uint32_t(StringsNonDebug.size()), uint32_t(Strings.size()), - uint32_t(Nodes.size()), uint32_t(Registers.size()), - uint32_t(Functions.size()), uint32_t(Enums.size()), - uint32_t(EnumValues.size()), uint32_t(Annotations.size()), - uint32_t(Arrays.size()), uint32_t(ArraySizes.size()), - uint32_t(MemberTypeIds.size()), uint32_t(Types.size()), - uint32_t(Buffers.size()), uint32_t(TypeList.size()), - uint32_t(Parameters.size()), uint32_t(Statements.size())}; + UnsafeCast(Bytes, + toReserve) = {ReflectionDataMagic, + ReflectionDataVersion, + uint16_t(Sources.size()), + Features, + uint32_t(StringsNonDebug.size()), + uint32_t(Strings.size()), + uint32_t(Nodes.size()), + uint32_t(Registers.size()), + uint32_t(Functions.size()), + uint32_t(Enums.size()), + uint32_t(EnumValues.size()), + uint32_t(Annotations.size()), + uint32_t(Arrays.size()), + uint32_t(ArraySizes.size()), + uint32_t(MemberTypeIds.size()), + uint32_t(Types.size()), + uint32_t(Buffers.size()), + uint32_t(TypeList.size()), + uint32_t(Parameters.size()), + uint32_t(Statements.size())}; toReserve += sizeof(DxcHLSLHeader); @@ -503,33 +513,33 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { switch (Type) { case D3D_SIT_CBUFFER: - return D3D_CT_CBUFFER; + return D3D_CT_CBUFFER; case D3D_SIT_TBUFFER: - return D3D_CT_TBUFFER; + return D3D_CT_TBUFFER; case D3D_SIT_STRUCTURED: case D3D_SIT_UAV_RWSTRUCTURED: case D3D_SIT_UAV_APPEND_STRUCTURED: case D3D_SIT_UAV_CONSUME_STRUCTURED: case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: - return D3D_CT_RESOURCE_BIND_INFO; + return D3D_CT_RESOURCE_BIND_INFO; default: - return D3D_CT_INTERFACE_POINTERS; + return D3D_CT_INTERFACE_POINTERS; } } -[[nodiscard]] ReflectionError ReflectionData::Deserialize(const std::vector &Bytes, - bool MakeNameLookupTable) -{ +[[nodiscard]] ReflectionError +ReflectionData::Deserialize(const std::vector &Bytes, + bool MakeNameLookupTable) { *this = {}; uint64_t off = 0; DxcHLSLHeader header; if (ReflectionError err = Consume(Bytes, off, header)) - return err; + return err; if (header.MagicNumber != ReflectionDataMagic) return HLSL_REFL_ERR("Invalid magic number"); @@ -539,8 +549,7 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { Features = header.Features; - bool hasSymbolInfo = - Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + bool hasSymbolInfo = Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; if (!hasSymbolInfo && (header.Sources || header.Strings)) return HLSL_REFL_ERR("Sources are invalid without symbols"); @@ -566,7 +575,7 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { if (off != Bytes.size()) return HLSL_REFL_ERR("Reflection info had unrecognized data on the back"); - for(uint32_t i = 0; i < header.Sources; ++i) + for (uint32_t i = 0; i < header.Sources; ++i) if (Sources[i] >= header.Strings) return HLSL_REFL_ERR("Source path out of bounds", i); @@ -577,8 +586,8 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { const ReflectionNode &node = Nodes[i]; if (hasSymbolInfo && (NodeSymbols[i].GetNameId() >= header.Strings || - (NodeSymbols[i].GetFileSourceId() != uint16_t(-1) && - NodeSymbols[i].GetFileSourceId() >= header.Sources))) + (NodeSymbols[i].GetFileSourceId() != uint16_t(-1) && + NodeSymbols[i].GetFileSourceId() >= header.Sources))) return HLSL_REFL_ERR("Node points to invalid name or file name", i); if (node.GetAnnotationStart() + node.GetAnnotationCount() > @@ -619,8 +628,8 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { if (Nodes[node.GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_FUNCTION) - return HLSL_REFL_ERR( - "Node is a parameter but parent isn't a function", i); + return HLSL_REFL_ERR("Node is a parameter but parent isn't a function", + i); break; @@ -647,9 +656,10 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { break; default: - return HLSL_REFL_ERR( - "Node is an if/scope/do/for/while/switch but parent isn't of a similar " - "type or function", i); + return HLSL_REFL_ERR("Node is an if/scope/do/for/while/switch but " + "parent isn't of a similar " + "type or function", + i); } break; @@ -679,7 +689,8 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { case D3D12_HLSL_NODE_TYPE_PARAMETER: if (node.GetChildCount()) return HLSL_REFL_ERR("Node is a parameter, typedef, variable or " - "static variable but also has children", i); + "static variable but also has children", + i); [[fallthrough]]; @@ -697,8 +708,8 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { node.GetNodeType() == D3D12_HLSL_NODE_TYPE_VARIABLE) && Nodes[node.GetParentId()].GetNodeType() == D3D12_HLSL_NODE_TYPE_INTERFACE) - return HLSL_REFL_ERR( - "Node is interface but has registers or variables", i); + return HLSL_REFL_ERR("Node is interface but has registers or variables", + i); if (node.IsFwdDeclare() && !allowFwdDeclare) return HLSL_REFL_ERR("Node is fwd declare but that's not permitted", i); @@ -707,34 +718,35 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { return HLSL_REFL_ERR("Node has invalid localId", i); } - for(uint32_t i = 0; i < header.Registers; ++i) { + for (uint32_t i = 0; i < header.Registers; ++i) { const ReflectionShaderResource ® = Registers[i]; - if(reg.GetNodeId() >= header.Nodes || - Nodes[reg.GetNodeId()].GetNodeType() != - D3D12_HLSL_NODE_TYPE_REGISTER || - Nodes[reg.GetNodeId()].GetLocalId() != i - ) + if (reg.GetNodeId() >= header.Nodes || + Nodes[reg.GetNodeId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_REGISTER || + Nodes[reg.GetNodeId()].GetLocalId() != i) return HLSL_REFL_ERR("Register points to an invalid nodeId", i); if (reg.GetType() > D3D_SIT_UAV_FEEDBACKTEXTURE || reg.GetReturnType() > D3D_RETURN_TYPE_CONTINUED || - reg.GetDimension() > D3D_SRV_DIMENSION_BUFFEREX || !reg.GetBindCount() || - (reg.GetArrayId() != uint32_t(-1) && reg.GetArrayId() >= header.Arrays) || + reg.GetDimension() > D3D_SRV_DIMENSION_BUFFEREX || + !reg.GetBindCount() || + (reg.GetArrayId() != uint32_t(-1) && + reg.GetArrayId() >= header.Arrays) || (reg.GetArrayId() != uint32_t(-1) && reg.GetBindCount() <= 1)) return HLSL_REFL_ERR( - "Register invalid type, returnType, bindCount, array or dimension", i); - - D3D_CBUFFER_TYPE bufferType = - ReflectionData::GetBufferType(reg.GetType()); + "Register invalid type, returnType, bindCount, array or dimension", + i); + + D3D_CBUFFER_TYPE bufferType = ReflectionData::GetBufferType(reg.GetType()); - if(bufferType != D3D_CT_INTERFACE_POINTERS) { + if (bufferType != D3D_CT_INTERFACE_POINTERS) { if (reg.GetBufferId() >= header.Buffers || Buffers[reg.GetBufferId()].NodeId != reg.GetNodeId() || Buffers[reg.GetBufferId()].Type != bufferType) - return HLSL_REFL_ERR("Register invalid buffer referenced by register", i); + return HLSL_REFL_ERR("Register invalid buffer referenced by register", + i); } } @@ -757,12 +769,12 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { if (Nodes[func.GetNodeId() + 1 + j].GetParentId() != func.GetNodeId() || Nodes[func.GetNodeId() + 1 + j].GetNodeType() != D3D12_HLSL_NODE_TYPE_PARAMETER) - return HLSL_REFL_ERR( - "Function is missing valid parameters and/or return", i); + return HLSL_REFL_ERR( + "Function is missing valid parameters and/or return", i); } - for(uint32_t i = 0; i < header.Enums; ++i) { - + for (uint32_t i = 0; i < header.Enums; ++i) { + const ReflectionEnumeration &enm = Enums[i]; if (enm.NodeId >= header.Nodes || @@ -780,21 +792,22 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { return HLSL_REFL_ERR("Enum has no values!", i); for (uint32_t j = 0; j < node.GetChildCount(); ++j) { - - const ReflectionNode &child = Nodes[enm.NodeId + 1 + j]; - if (child.GetChildCount() != 0 || - child.GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM_VALUE) - return HLSL_REFL_ERR("Enum has an invalid enum value", i); + const ReflectionNode &child = Nodes[enm.NodeId + 1 + j]; + + if (child.GetChildCount() != 0 || + child.GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM_VALUE) + return HLSL_REFL_ERR("Enum has an invalid enum value", i); } } - for(uint32_t i = 0; i < header.EnumValues; ++i) { - + for (uint32_t i = 0; i < header.EnumValues; ++i) { + const ReflectionEnumValue &enumVal = EnumValues[i]; if (enumVal.NodeId >= header.Nodes || - Nodes[enumVal.NodeId].GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM_VALUE || + Nodes[enumVal.NodeId].GetNodeType() != + D3D12_HLSL_NODE_TYPE_ENUM_VALUE || Nodes[enumVal.NodeId].GetLocalId() != i || Nodes[Nodes[enumVal.NodeId].GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM) @@ -835,7 +848,7 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { if (child.GetChildCount() != 0 || child.GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) - return HLSL_REFL_ERR("Buffer has to have only Variable child nodes", i); + return HLSL_REFL_ERR("Buffer has to have only Variable child nodes", i); } } @@ -918,7 +931,8 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { if (condVar && Nodes[Stmt.GetNodeId() + 1].GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) return HLSL_REFL_ERR( - "Statement has condition variable but first child is not a variable", i); + "Statement has condition variable but first child is not a variable", + i); switch (Nodes[Stmt.GetNodeId()].GetNodeType()) { case D3D12_HLSL_NODE_TYPE_IF: @@ -930,7 +944,7 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { return HLSL_REFL_ERR("Statement has invalid node type", i); } } - + for (uint32_t i = 0; i < header.Types; ++i) { const ReflectionVariableType &type = Types[i]; @@ -939,9 +953,8 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { TypeSymbols[i].UnderlyingNameId >= header.Strings)) return HLSL_REFL_ERR("Type points to an invalid string", i); - if (hasSymbolInfo && - (TypeSymbols[i].DisplayArray.ElementsOrArrayId >> 31 && - (TypeSymbols[i].DisplayArray.ElementsOrArrayId << 1 >> + if (hasSymbolInfo && (TypeSymbols[i].DisplayArray.ElementsOrArrayId >> 31 && + (TypeSymbols[i].DisplayArray.ElementsOrArrayId << 1 >> 1) >= header.Arrays)) return HLSL_REFL_ERR("Type points to an invalid string", i); @@ -961,104 +974,106 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { case D3D_SVC_SCALAR: if (type.GetColumns() != 1) - return HLSL_REFL_ERR("Type (scalar) should have columns == 1", i); + return HLSL_REFL_ERR("Type (scalar) should have columns == 1", i); [[fallthrough]]; case D3D_SVC_VECTOR: if (type.GetRows() != 1) - return HLSL_REFL_ERR("Type (scalar/vector) should have rows == 1", i); + return HLSL_REFL_ERR("Type (scalar/vector) should have rows == 1", i); [[fallthrough]]; case D3D_SVC_MATRIX_ROWS: case D3D_SVC_MATRIX_COLUMNS: - if (!type.GetRows() || !type.GetColumns() || type.GetRows() > 128 || + if (!type.GetRows() || !type.GetColumns() || type.GetRows() > 128 || type.GetColumns() > 128) - return HLSL_REFL_ERR("Type (scalar/vector/matrix) has invalid rows or columns", i); - - switch (type.GetType()) { - case D3D_SVT_BOOL: - case D3D_SVT_INT: - case D3D_SVT_FLOAT: - case D3D_SVT_MIN8FLOAT: - case D3D_SVT_MIN10FLOAT: - case D3D_SVT_MIN16FLOAT: - case D3D_SVT_MIN12INT: - case D3D_SVT_MIN16INT: - case D3D_SVT_MIN16UINT: - case D3D_SVT_INT16: - case D3D_SVT_UINT16: - case D3D_SVT_FLOAT16: - case D3D_SVT_INT64: - case D3D_SVT_UINT64: - case D3D_SVT_UINT: - case D3D_SVT_DOUBLE: - break; - - default: - return HLSL_REFL_ERR("Type (scalar/matrix/vector) is of invalid type", i); - } - + return HLSL_REFL_ERR( + "Type (scalar/vector/matrix) has invalid rows or columns", i); + + switch (type.GetType()) { + case D3D_SVT_BOOL: + case D3D_SVT_INT: + case D3D_SVT_FLOAT: + case D3D_SVT_MIN8FLOAT: + case D3D_SVT_MIN10FLOAT: + case D3D_SVT_MIN16FLOAT: + case D3D_SVT_MIN12INT: + case D3D_SVT_MIN16INT: + case D3D_SVT_MIN16UINT: + case D3D_SVT_INT16: + case D3D_SVT_UINT16: + case D3D_SVT_FLOAT16: + case D3D_SVT_INT64: + case D3D_SVT_UINT64: + case D3D_SVT_UINT: + case D3D_SVT_DOUBLE: break; + default: + return HLSL_REFL_ERR("Type (scalar/matrix/vector) is of invalid type", + i); + } + + break; + case D3D_SVC_STRUCT: - if (!type.GetMemberCount()) - return HLSL_REFL_ERR("Type (struct) is missing children", i); + if (!type.GetMemberCount()) + return HLSL_REFL_ERR("Type (struct) is missing children", i); - [[fallthrough]]; + [[fallthrough]]; case D3D_SVC_INTERFACE_CLASS: - if (type.GetType()) - return HLSL_REFL_ERR("Type (struct) shouldn't have rows or columns", i); + if (type.GetType()) + return HLSL_REFL_ERR("Type (struct) shouldn't have rows or columns", i); - if (type.GetRows() || type.GetColumns()) - return HLSL_REFL_ERR("Type (struct) shouldn't have rows or columns", i); + if (type.GetRows() || type.GetColumns()) + return HLSL_REFL_ERR("Type (struct) shouldn't have rows or columns", i); - break; + break; case D3D_SVC_OBJECT: - switch (type.GetType()) { - - case D3D_SVT_STRING: - case D3D_SVT_TEXTURE1D: - case D3D_SVT_TEXTURE2D: - case D3D_SVT_TEXTURE3D: - case D3D_SVT_TEXTURECUBE: - case D3D_SVT_SAMPLER: - case D3D_SVT_BUFFER: - case D3D_SVT_CBUFFER: - case D3D_SVT_TBUFFER: - case D3D_SVT_TEXTURE1DARRAY: - case D3D_SVT_TEXTURE2DARRAY: - case D3D_SVT_TEXTURE2DMS: - case D3D_SVT_TEXTURE2DMSARRAY: - case D3D_SVT_TEXTURECUBEARRAY: - case D3D_SVT_RWTEXTURE1D: - case D3D_SVT_RWTEXTURE1DARRAY: - case D3D_SVT_RWTEXTURE2D: - case D3D_SVT_RWTEXTURE2DARRAY: - case D3D_SVT_RWTEXTURE3D: - case D3D_SVT_RWBUFFER: - case D3D_SVT_BYTEADDRESS_BUFFER: - case D3D_SVT_RWBYTEADDRESS_BUFFER: - case D3D_SVT_STRUCTURED_BUFFER: - case D3D_SVT_RWSTRUCTURED_BUFFER: - case D3D_SVT_APPEND_STRUCTURED_BUFFER: - case D3D_SVT_CONSUME_STRUCTURED_BUFFER: - break; - - default: - return HLSL_REFL_ERR("Type (object) is of invalid type", i); - } + switch (type.GetType()) { + + case D3D_SVT_STRING: + case D3D_SVT_TEXTURE1D: + case D3D_SVT_TEXTURE2D: + case D3D_SVT_TEXTURE3D: + case D3D_SVT_TEXTURECUBE: + case D3D_SVT_SAMPLER: + case D3D_SVT_BUFFER: + case D3D_SVT_CBUFFER: + case D3D_SVT_TBUFFER: + case D3D_SVT_TEXTURE1DARRAY: + case D3D_SVT_TEXTURE2DARRAY: + case D3D_SVT_TEXTURE2DMS: + case D3D_SVT_TEXTURE2DMSARRAY: + case D3D_SVT_TEXTURECUBEARRAY: + case D3D_SVT_RWTEXTURE1D: + case D3D_SVT_RWTEXTURE1DARRAY: + case D3D_SVT_RWTEXTURE2D: + case D3D_SVT_RWTEXTURE2DARRAY: + case D3D_SVT_RWTEXTURE3D: + case D3D_SVT_RWBUFFER: + case D3D_SVT_BYTEADDRESS_BUFFER: + case D3D_SVT_RWBYTEADDRESS_BUFFER: + case D3D_SVT_STRUCTURED_BUFFER: + case D3D_SVT_RWSTRUCTURED_BUFFER: + case D3D_SVT_APPEND_STRUCTURED_BUFFER: + case D3D_SVT_CONSUME_STRUCTURED_BUFFER: + break; - if (type.GetRows() || type.GetColumns()) - return HLSL_REFL_ERR("Type (object) shouldn't have rows or columns", i); + default: + return HLSL_REFL_ERR("Type (object) is of invalid type", i); + } + + if (type.GetRows() || type.GetColumns()) + return HLSL_REFL_ERR("Type (object) shouldn't have rows or columns", i); break; @@ -1067,9 +1082,9 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { } } - //Validate fwd & backwards declares + // Validate fwd & backwards declares - for (uint32_t i = 0; i < header.Nodes; ++i) { + for (uint32_t i = 0; i < header.Nodes; ++i) { const ReflectionNode &node = Nodes[i]; @@ -1078,23 +1093,24 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { uint32_t fwdBack = node.GetFwdBck(); if (Nodes[fwdBack].GetNodeType() != node.GetNodeType()) - return HLSL_REFL_ERR( - "Node (fwd/bck declare) points to element that of incompatible type", i); + return HLSL_REFL_ERR("Node (fwd/bck declare) points to element that of " + "incompatible type", + i); - if (hasSymbolInfo && NodeSymbols[fwdBack].GetNameId() != - NodeSymbols[i].GetNameId()) - return HLSL_REFL_ERR( - "Node (fwd/bck declare) have mismatching name", i); + if (hasSymbolInfo && + NodeSymbols[fwdBack].GetNameId() != NodeSymbols[i].GetNameId()) + return HLSL_REFL_ERR("Node (fwd/bck declare) have mismatching name", i); if (node.IsFwdDeclare()) { if (fwdBack <= i || fwdBack >= header.Nodes) - return HLSL_REFL_ERR( - "Node (fwd declare) points to invalid element", i); + return HLSL_REFL_ERR("Node (fwd declare) points to invalid element", + i); if (Nodes[fwdBack].IsFwdDeclare()) return HLSL_REFL_ERR( - "Node (fwd declare) points to element that is also a fwd declare", i); + "Node (fwd declare) points to element that is also a fwd declare", + i); uint32_t paramCount = 0; @@ -1106,23 +1122,25 @@ D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { if ((node.GetChildCount() != paramCount) || node.GetAnnotationCount()) return HLSL_REFL_ERR( "Node (fwd declare) points to element with invalid child count, " - "or annotationCount", i); + "or annotationCount", + i); } else { if (fwdBack >= i) - return HLSL_REFL_ERR( - "Node (bck declare) points to invalid element", i); + return HLSL_REFL_ERR("Node (bck declare) points to invalid element", + i); if (!Nodes[fwdBack].IsFwdDeclare()) return HLSL_REFL_ERR( - "Node (bck declare) points to element that is not a fwd declare", i); + "Node (bck declare) points to element that is not a fwd declare", + i); } } } - //Finalize + // Finalize if (MakeNameLookupTable) GenerateNameLookupTable(); diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 596888169a..aac363f122 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -8,11 +8,11 @@ /////////////////////////////////////////////////////////////////////////////// #include "dxc/DxcReflection/DxcReflectionContainer.h" -#include #include +#include namespace hlsl { - + struct JsonWriter { std::stringstream ss; @@ -213,14 +213,15 @@ struct JsonWriter { } ~ArrayScope() { W.EndArray(); } }; - + void Object(const char *Name, const std::function &Body) { ObjectScope _(*this, Name); Body(); } void Array(const char *Name, const std::function &Body) { - ArrayScope _( *this, Name ); Body(); + ArrayScope _(*this, Name); + Body(); } void StringField(const char *K, const std::string &V) { @@ -354,11 +355,12 @@ static std::string BufferTypeToString(D3D_CBUFFER_TYPE Type) { } static std::string GetBuiltinTypeName(const ReflectionData &Refl, - const ReflectionVariableType &Type) { + const ReflectionVariableType &Type) { std::string type = ""; - if (Type.GetClass() != D3D_SVC_STRUCT && Type.GetClass() != D3D_SVC_INTERFACE_CLASS) { + if (Type.GetClass() != D3D_SVC_STRUCT && + Type.GetClass() != D3D_SVC_INTERFACE_CLASS) { static const char *arr[] = {"void", "bool", @@ -475,8 +477,7 @@ struct ReflectionPrintSettings { bool HideFileInfo; }; -static void PrintSymbol(JsonWriter &Json, - const ReflectionData &Reflection, +static void PrintSymbol(JsonWriter &Json, const ReflectionData &Reflection, const ReflectionNodeSymbol &Sym, const ReflectionPrintSettings &Settings, bool MuteName) { @@ -513,7 +514,8 @@ static void PrintSymbol(JsonWriter &Json, // Verbose and all members are slightly different; // Verbose will still print fields even if they aren't relevant, -// while all members will not silence important info but that might not matter for human readability +// while all members will not silence important info but that might not matter +// for human readability static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, uint32_t NodeId, const ReflectionPrintSettings &Settings) { @@ -749,27 +751,27 @@ static void PrintType(const ReflectionData &Reflection, uint32_t TypeId, NameForTypeName); if (type.GetBaseClass() != uint32_t(-1)) - Json.Object("BaseClass", [&Reflection, &Json, &type, HasSymbols, Settings, - Recursive]() { - if (Recursive) - PrintType(Reflection, type.GetBaseClass(), HasSymbols, Settings, Json, - true, "TypeName"); - - else - PrintTypeName(Reflection, type.GetBaseClass(), HasSymbols, Settings, - Json, "TypeName"); - }); + Json.Object("BaseClass", + [&Reflection, &Json, &type, HasSymbols, Settings, Recursive]() { + if (Recursive) + PrintType(Reflection, type.GetBaseClass(), HasSymbols, + Settings, Json, true, "TypeName"); + + else + PrintTypeName(Reflection, type.GetBaseClass(), HasSymbols, + Settings, Json, "TypeName"); + }); if (type.GetInterfaceCount()) - Json.Array("Interfaces", [&Reflection, &Json, &type, HasSymbols, - Settings]() { - for (uint32_t i = 0; i < uint32_t(type.GetInterfaceCount()); ++i) { - uint32_t interfaceId = type.GetInterfaceStart() + i; - JsonWriter::ObjectScope nodeRoot(Json); - PrintTypeName(Reflection, Reflection.TypeList[interfaceId], HasSymbols, - Settings, Json); - } - }); + Json.Array( + "Interfaces", [&Reflection, &Json, &type, HasSymbols, Settings]() { + for (uint32_t i = 0; i < uint32_t(type.GetInterfaceCount()); ++i) { + uint32_t interfaceId = type.GetInterfaceStart() + i; + JsonWriter::ObjectScope nodeRoot(Json); + PrintTypeName(Reflection, Reflection.TypeList[interfaceId], + HasSymbols, Settings, Json); + } + }); if (type.GetMemberCount()) Json.Array("Members", [&Reflection, &Json, &type, HasSymbols, Settings, @@ -1010,8 +1012,8 @@ static uint32_t PrintBufferMember(const ReflectionData &Reflection, Json.StringField( "Name", Reflection.Strings[Reflection.NodeSymbols[NodeId].GetNameId()]); - PrintType(Reflection, node.GetLocalId(), HasSymbols, Settings, Json, - true, "TypeName"); + PrintType(Reflection, node.GetLocalId(), HasSymbols, Settings, Json, true, + "TypeName"); return node.GetChildCount(); } @@ -1108,7 +1110,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - + ReflectionNode node = Reflection.Nodes[NodeId]; // In case we're a fwd declare, don't change how we walk the tree @@ -1181,7 +1183,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, if (type.GetInterfaceCount()) Json.Array("Interfaces", [&Json, &type, &Reflection, hasSymbols, - &Settings]() { + &Settings]() { for (uint32_t i = 0; i < uint32_t(type.GetInterfaceCount()); ++i) { uint32_t interfaceId = type.GetInterfaceStart() + i; JsonWriter::ObjectScope nodeRoot(Json); @@ -1236,15 +1238,17 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, Json.Object(stmtType, [&node, &Reflection, &Json, &Settings, NodeId, &childrenToSkip, nodeType]() { - const ReflectionScopeStmt &stmt = Reflection.Statements[node.GetLocalId()]; + const ReflectionScopeStmt &stmt = + Reflection.Statements[node.GetLocalId()]; uint32_t start = NodeId + 1; if (stmt.HasConditionVar()) - Json.Object("Condition", [NodeId, &Reflection, &Json, &start, &Settings]() { - start += PrintNodeRecursive(Reflection, start, Json, Settings); - ++start; - }); + Json.Object( + "Condition", [NodeId, &Reflection, &Json, &start, &Settings]() { + start += PrintNodeRecursive(Reflection, start, Json, Settings); + ++start; + }); uint32_t end = start + stmt.GetNodeCount(); @@ -1269,18 +1273,19 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, } // Children - + uint32_t start = NodeId + 1 + childrenToSkip; uint32_t end = NodeId + 1 + node.GetChildCount(); PrintChildren(Reflection, Json, "Children", start, end, Settings); - + return nodeChildCountForRet; } // IsHumanFriendly = false: Raw view of the real file data // IsHumanFriendly = true: Clean view that's relatively close to the real tree -std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) const { +std::string ReflectionData::ToJson(bool HideFileInfo, + bool IsHumanFriendly) const { JsonWriter json; @@ -1291,8 +1296,7 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons PrintFeatures(Features, json); - bool hasSymbols = - Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; + bool hasSymbols = Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; ReflectionPrintSettings settings{}; settings.HideFileInfo = HideFileInfo; @@ -1371,12 +1375,13 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons } }); - json.Array("EnumValues", [this, &json, hasSymbols, HideFileInfo, &settings] { - for (uint32_t i = 0; i < uint32_t(EnumValues.size()); ++i) { - JsonWriter::ObjectScope valueRoot(json); - PrintEnumValue(json, *this, EnumValues[i].NodeId, settings); - } - }); + json.Array( + "EnumValues", [this, &json, hasSymbols, HideFileInfo, &settings] { + for (uint32_t i = 0; i < uint32_t(EnumValues.size()); ++i) { + JsonWriter::ObjectScope valueRoot(json); + PrintEnumValue(json, *this, EnumValues[i].NodeId, settings); + } + }); json.Array("Annotations", [this, &json, hasSymbols] { for (uint32_t i = 0; i < uint32_t(Annotations.size()); ++i) { @@ -1416,8 +1421,8 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons json.UIntField("NameId", MemberNameIds[i]); } - PrintTypeName(*this, MemberTypeIds[i], hasSymbols, settings, - json, "TypeName"); + PrintTypeName(*this, MemberTypeIds[i], hasSymbols, settings, json, + "TypeName"); } }); @@ -1446,8 +1451,7 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons const ReflectionScopeStmt &stat = Statements[i]; JsonWriter::ObjectScope valueRoot(json); json.StringField( - "Type", NodeTypeToString( - Nodes[stat.GetNodeId()].GetNodeType())); + "Type", NodeTypeToString(Nodes[stat.GetNodeId()].GetNodeType())); json.UIntField("NodeId", stat.GetNodeId()); PrintStatement(*this, stat, json); @@ -1456,8 +1460,7 @@ std::string ReflectionData::ToJson(bool HideFileInfo, bool IsHumanFriendly) cons } else - PrintChildren(*this, json, "Children", 1, Nodes.size(), - settings); + PrintChildren(*this, json, "Children", 1, Nodes.size(), settings); } return json.str(); diff --git a/tools/clang/tools/dxreflector/dxreflector.cpp b/tools/clang/tools/dxreflector/dxreflector.cpp index 67f4172017..4852f1b452 100644 --- a/tools/clang/tools/dxreflector/dxreflector.cpp +++ b/tools/clang/tools/dxreflector/dxreflector.cpp @@ -59,8 +59,8 @@ int main(int argc, const char **argv) { std::string errorString; llvm::raw_string_ostream errorStream(errorString); - // Target profile is used to detect for example if 16-bit types are allowed. - // This is the only way to correct the missing target. + // Target profile is used to detect for example if 16-bit types are + // allowed. This is the only way to correct the missing target. { unsigned missingArgIndex = 0, missingArgCount = 0; @@ -91,8 +91,8 @@ int main(int argc, const char **argv) { } } - int optResult = - ReadDxcOpts(optionTable, DxreflectorFlags, argStrings, dxreflectorOpts, errorStream); + int optResult = ReadDxcOpts(optionTable, DxreflectorFlags, argStrings, + dxreflectorOpts, errorStream); errorStream.flush(); if (errorString.size()) { fprintf(stderr, "dxreflector failed : %s\n", errorString.data()); @@ -103,7 +103,8 @@ int main(int argc, const char **argv) { } // Apply defaults. - if (dxreflectorOpts.EntryPoint.empty() && !dxreflectorOpts.RecompileFromBinary) { + if (dxreflectorOpts.EntryPoint.empty() && + !dxreflectorOpts.RecompileFromBinary) { dxreflectorOpts.EntryPoint = "main"; } @@ -128,13 +129,14 @@ int main(int argc, const char **argv) { llvm::raw_string_ostream helpStream(helpString); std::string version; llvm::raw_string_ostream versionStream(version); - WriteDxCompilerVersionInfo( - versionStream, - dxreflectorOpts.ExternalLib.empty() ? (LPCSTR) nullptr - : dxreflectorOpts.ExternalLib.data(), - dxreflectorOpts.ExternalFn.empty() ? (LPCSTR) nullptr + WriteDxCompilerVersionInfo(versionStream, + dxreflectorOpts.ExternalLib.empty() + ? (LPCSTR) nullptr + : dxreflectorOpts.ExternalLib.data(), + dxreflectorOpts.ExternalFn.empty() + ? (LPCSTR) nullptr : dxreflectorOpts.ExternalFn.data(), - dxcSupport); + dxcSupport); versionStream.flush(); optionTable->PrintHelp(helpStream, "dxreflector.exe", "DX Reflector", version.c_str(), hlsl::options::ReflectOption, @@ -147,13 +149,14 @@ int main(int argc, const char **argv) { if (dxreflectorOpts.ShowVersion) { std::string version; llvm::raw_string_ostream versionStream(version); - WriteDxCompilerVersionInfo( - versionStream, - dxreflectorOpts.ExternalLib.empty() ? (LPCSTR) nullptr - : dxreflectorOpts.ExternalLib.data(), - dxreflectorOpts.ExternalFn.empty() ? (LPCSTR) nullptr + WriteDxCompilerVersionInfo(versionStream, + dxreflectorOpts.ExternalLib.empty() + ? (LPCSTR) nullptr + : dxreflectorOpts.ExternalLib.data(), + dxreflectorOpts.ExternalFn.empty() + ? (LPCSTR) nullptr : dxreflectorOpts.ExternalFn.data(), - dxcSupport); + dxcSupport); versionStream.flush(); WriteUtf8ToConsoleSizeT(version.data(), version.size()); return 0; @@ -162,8 +165,9 @@ int main(int argc, const char **argv) { CComPtr pReflector; CComPtr pRewriteResult; CComPtr pSource; - std::wstring wName( - CA2W(dxreflectorOpts.InputFile.empty() ? "" : dxreflectorOpts.InputFile.data())); + std::wstring wName(CA2W(dxreflectorOpts.InputFile.empty() + ? "" + : dxreflectorOpts.InputFile.data())); if (!dxreflectorOpts.InputFile.empty()) ReadFileIntoBlob(dxcSupport, wName.c_str(), &pSource); @@ -190,9 +194,11 @@ int main(int argc, const char **argv) { if (dxreflectorOpts.OutputObject.empty()) { // No -Fo, print to console - WriteOperationResultToConsole(pRewriteResult, !dxreflectorOpts.OutputWarnings); + WriteOperationResultToConsole(pRewriteResult, + !dxreflectorOpts.OutputWarnings); } else { - WriteOperationErrorsToConsole(pRewriteResult, !dxreflectorOpts.OutputWarnings); + WriteOperationErrorsToConsole(pRewriteResult, + !dxreflectorOpts.OutputWarnings); HRESULT hr; IFT(pRewriteResult->GetStatus(&hr)); if (SUCCEEDED(hr)) { From 546a28d502c540e1f0be3df13b238f0bb332dcaf Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 11 Nov 2025 16:38:50 +0100 Subject: [PATCH 107/126] Formatting on _ast.cpp after adding missing includes --- .../dxcreflection/dxcreflection_from_ast.cpp | 345 +++++++++--------- 1 file changed, 182 insertions(+), 163 deletions(-) diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 1610a6e8db..9e37429df7 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -9,30 +9,45 @@ // // /////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" + +#include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/HlslTypes.h" #include "clang/AST/DeclVisitor.h" +#include "clang/AST/Expr.h" +#include "clang/AST/HlslTypes.h" +#include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" -#include "clang/Frontend/CompilerInstance.h" +#include "clang/AST/TemplateBase.h" #include "clang/Basic/SourceManager.h" +#include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/Lexer.h" + #include "dxc/DxcReflection/DxcReflectionContainer.h" using namespace clang; namespace hlsl { - + [[nodiscard]] static ReflectionError PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, const LangOptions &LangOpts, const std::string &UnqualifiedName, const Decl *DeclSelf, D3D12_HLSL_NODE_TYPE Type, uint32_t ParentNodeId, uint32_t LocalId, const SourceRange *Range = nullptr, - std::unordered_map *FwdDecls = nullptr) -{ - + std::unordered_map *FwdDecls = nullptr) { + if (Refl.Nodes.size() >= (1u << 24)) return HLSL_REFL_ERR("Nodes overflow"); @@ -57,14 +72,12 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, uint32_t stringId; - if (ReflectionError err = - Refl.RegisterString(stringId, annotate->getAnnotation().str(), true)) + if (ReflectionError err = Refl.RegisterString( + stringId, annotate->getAnnotation().str(), true)) return err; if (ReflectionError err = ReflectionAnnotation::Initialize( - Refl.Annotations.back(), - stringId, - false)) + Refl.Annotations.back(), stringId, false)) return err; if (annotationCount >= uint8_t(-1)) @@ -83,13 +96,12 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, uint32_t stringId; if (ReflectionError err = Refl.RegisterString( - stringId, "shader(\"" + shaderAttr->getStage().str() + "\")", true)) + stringId, "shader(\"" + shaderAttr->getStage().str() + "\")", + true)) return err; if (ReflectionError err = ReflectionAnnotation::Initialize( - Refl.Annotations.back(), - stringId, - true)) + Refl.Annotations.back(), stringId, true)) return err; if (annotationCount >= uint8_t(-1)) @@ -113,8 +125,7 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, if (ReflectionError err = Refl.RegisterString( semanticId32, - cast(*It)->SemanticName.str(), - true)) + cast(*It)->SemanticName.str(), true)) return err; semanticId = uint16_t(semanticId32); @@ -128,19 +139,19 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, const Decl *fwdDeclare = nullptr; if (DeclSelf) { - + if (const FunctionDecl *func = dyn_cast(DeclSelf)) { isFwdDeclare = !func->doesThisDeclarationHaveABody(); fwdDeclare = func->getCanonicalDecl(); canHaveFwdDeclare = true; } - + else if (const EnumDecl *enm = dyn_cast(DeclSelf)) { isFwdDeclare = !enm->isCompleteDefinition(); fwdDeclare = enm->getCanonicalDecl(); canHaveFwdDeclare = true; } - + else if (const RecordDecl *rec = dyn_cast(DeclSelf)) { isFwdDeclare = !rec->isThisDeclarationADefinition(); @@ -165,9 +176,9 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, NodeId = uint32_t(-1); return ReflectionErrorSuccess; } - + if (isFwdDeclare) - (*FwdDecls)[fwdDeclare] = currId; + (*FwdDecls)[fwdDeclare] = currId; } Refl.Nodes.push_back({}); @@ -193,14 +204,14 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, if (start.isValid() && end.isValid()) { - PresumedLoc presumed = SM.getPresumedLoc(start); + PresumedLoc presumed = SM.getPresumedLoc(start); - SourceLocation realEnd = SM.getFileLoc(end); - SourceLocation endOfToken = - Lexer::getLocForEndOfToken(realEnd, 0, SM, LangOpts); - PresumedLoc presumedEnd = SM.getPresumedLoc(endOfToken); + SourceLocation realEnd = SM.getFileLoc(end); + SourceLocation endOfToken = + Lexer::getLocForEndOfToken(realEnd, 0, SM, LangOpts); + PresumedLoc presumedEnd = SM.getPresumedLoc(endOfToken); - if (presumed.isValid() && presumedEnd.isValid()) { + if (presumed.isValid() && presumedEnd.isValid()) { uint32_t startLine = presumed.getLine(); uint32_t startCol = presumed.getColumn(); @@ -252,27 +263,28 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, sourceColumnStart = startCol; sourceColumnEnd = endCol; sourceId = uint16_t(i); - } + } } uint32_t nameId; if (ReflectionError err = Refl.RegisterString(nameId, UnqualifiedName, false)) - return err; + return err; Refl.NodeSymbols.push_back({}); if (ReflectionError err = ReflectionNodeSymbol::Initialize( Refl.NodeSymbols.back(), nameId, sourceId, sourceLineCount, sourceLineStart, sourceColumnStart, sourceColumnEnd)) - return err; + return err; } // Link if (DeclSelf && fwdDeclare != DeclSelf && fwdDeclare && !isFwdDeclare) { - assert(FwdDecls && "Referencing fwd decl requires FwdDecls map to be present"); + assert(FwdDecls && + "Referencing fwd decl requires FwdDecls map to be present"); uint32_t fwd = (*FwdDecls)[fwdDeclare]; if (ReflectionError err = @@ -306,22 +318,22 @@ struct DxcRegisterTypeInfo { D3D_RESOURCE_RETURN_TYPE TextureValue; }; -static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, - std::string TypeName, - bool IsWrite, - const CXXRecordDecl *RecordDecl) { - +static DxcRegisterTypeInfo +GetTextureRegisterInfo(ASTContext &ASTCtx, std::string TypeName, bool IsWrite, + const CXXRecordDecl *RecordDecl) { + DxcRegisterTypeInfo type = {}; type.RegisterType = IsWrite ? D3D_SIT_UAV_RWTYPED : D3D_SIT_TEXTURE; - //Parse return type and dimensions + // Parse return type and dimensions const ClassTemplateSpecializationDecl *textureTemplate = dyn_cast(RecordDecl); assert(textureTemplate && "Expected texture template"); - const ArrayRef& textureParams = textureTemplate->getTemplateArgs().asArray(); + const ArrayRef &textureParams = + textureTemplate->getTemplateArgs().asArray(); bool shouldBeTexture2DMS = textureParams.size() == 2; @@ -330,9 +342,10 @@ static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, textureParams[1].getKind() == TemplateArgument::Integral && "Expected template args"); - else assert(textureParams.size() == 1 && - textureParams[0].getKind() == TemplateArgument::Type && - "Expected template args"); + else + assert(textureParams.size() == 1 && + textureParams[0].getKind() == TemplateArgument::Type && + "Expected template args"); QualType valueType = textureParams[0].getAsType(); QualType desugared = valueType.getDesugaredType(ASTCtx); @@ -401,7 +414,7 @@ static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, break; } - //Parse type + // Parse type if (TypeName == "Buffer") { assert(!shouldBeTexture2DMS && "Buffer expected but got Buffer"); @@ -443,7 +456,7 @@ static DxcRegisterTypeInfo GetTextureRegisterInfo(ASTContext &ASTCtx, (type.TextureDimension == D3D_SRV_DIMENSION_TEXTURE2DMS)) && "Texture2DMS used with Texture2D syntax or reverse"); - if (isArray) //Arrays are always 1 behind the regular type + if (isArray) // Arrays are always 1 behind the regular type type.TextureDimension = (D3D_SRV_DIMENSION)(type.TextureDimension + 1); return type; @@ -469,7 +482,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, ? D3D_SIF_COMPARISON_SAMPLER : (D3D_SHADER_INPUT_FLAGS)0}; } - + DxcRegisterTypeInfo info = {}; if (typeName == "AppendStructuredBuffer") { @@ -504,8 +517,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, typeName = typeName.substr(2); if (typeName == "StructuredBuffer") { - info.RegisterType = - isWrite ? D3D_SIT_UAV_RWSTRUCTURED : D3D_SIT_STRUCTURED; + info.RegisterType = isWrite ? D3D_SIT_UAV_RWSTRUCTURED : D3D_SIT_STRUCTURED; return info; } @@ -518,14 +530,15 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); } -[[nodiscard]] ReflectionError GenerateTypeInfo(uint32_t &TypeId, ASTContext &ASTCtx, ReflectionData &Refl, - QualType Original, bool DefaultRowMaj) { +[[nodiscard]] ReflectionError +GenerateTypeInfo(uint32_t &TypeId, ASTContext &ASTCtx, ReflectionData &Refl, + QualType Original, bool DefaultRowMaj) { // Unwrap array // There's the following issue: // Let's say the underlying type is F32x4[4] but the sugared name is F32x4x4, - // then we want to maintain sugared name + array info (of sugar) for reflection - // but for low level type info, we would want to know float4[4] + // then we want to maintain sugared name + array info (of sugar) for + // reflection but for low level type info, we would want to know float4[4] uint32_t arraySizeUnderlying = 1; QualType underlying = Original.getNonReferenceType().getCanonicalType(); @@ -577,10 +590,11 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, std::string underlyingName = underlying.getUnqualifiedType().getAsString(policy); - //Prune template instantiation from type name for builtin types (ex. vector & matrix) - //But only if it's not a sugared type: - // typedef ConstantBuffer MyTest; - //In this case, MyTest will still be seen as a ConstantBuffer but the typeName is MyTest. + // Prune template instantiation from type name for builtin types (ex. vector & + // matrix) But only if it's not a sugared type: + // typedef ConstantBuffer MyTest; + // In this case, MyTest will still be seen as a ConstantBuffer but the + // typeName is MyTest. static const std::unordered_map lookup = std::unordered_map{ @@ -622,7 +636,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, if (it != lookup.end()) { - if(it->second >= 0) + if (it->second >= 0) displayName = underlyingName = it->first; } } @@ -630,25 +644,27 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, bool hasSymbols = Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; - //Two arrays; for display and for underlying + // Two arrays; for display and for underlying uint32_t arrayIdUnderlying; - + if (ReflectionError err = Refl.PushArray( arrayIdUnderlying, arraySizeUnderlying, arrayElemUnderlying)) return err; - ReflectionArrayOrElements elementsOrArrayIdUnderlying(arrayIdUnderlying, arraySizeUnderlying); + ReflectionArrayOrElements elementsOrArrayIdUnderlying(arrayIdUnderlying, + arraySizeUnderlying); uint32_t arrayIdDisplay; if (ReflectionError err = Refl.PushArray(arrayIdDisplay, arraySizeDisplay, arrayElemDisplay)) return err; - ReflectionArrayOrElements elementsOrArrayIdDisplay(arrayIdDisplay, arraySizeDisplay); + ReflectionArrayOrElements elementsOrArrayIdDisplay(arrayIdDisplay, + arraySizeDisplay); - //Unwrap vector and matrix - //And base type + // Unwrap vector and matrix + // And base type D3D_SHADER_VARIABLE_CLASS cls = D3D_SVC_STRUCT; @@ -672,12 +688,12 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, if (const RecordType *record = underlying->getAs()) { - bool standardType = false; + bool standardType = false; - RecordDecl *recordDecl = record->getDecl(); + RecordDecl *recordDecl = record->getDecl(); - QualType innerType; - std::string innerTypeName; //$Element or T depending on type + QualType innerType; + std::string innerTypeName; //$Element or T depending on type if (const ClassTemplateSpecializationDecl *templateClass = dyn_cast(recordDecl)) { @@ -690,10 +706,10 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, auto it = lookup.find(name); if (it != lookup.end()) { - + D3D_SHADER_VARIABLE_TYPE svt = it->second; - if (svt == -1) { //Reserved as 'vector' + if (svt == -1) { // Reserved as 'vector' rows = 1; @@ -708,7 +724,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, standardType = true; } - else if (svt == -2) { //Reserved as 'matrix' + else if (svt == -2) { // Reserved as 'matrix' assert(params.size() == 3 && params[0].getKind() == TemplateArgument::Type && @@ -742,13 +758,13 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, const TemplateSpecializationType *templateDesc = display->getAs(); - // Case 1: T = StructuredBuffer then underlying has a type, but sugared doesn't. - // Loses syntax sugar, but will still be correct. + // Case 1: T = StructuredBuffer then underlying has a type, but + // sugared doesn't. Loses syntax sugar, but will still be correct. bool useUnderlying = !templateDesc; - // Case 2: TextureCube = TextureCube - + // Case 2: TextureCube = TextureCube + if (templateDesc && displayName == underlyingName && !templateDesc->getNumArgs()) useUnderlying = true; @@ -823,7 +839,8 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, // Fill members - if (!standardType && recordDecl->isCompleteDefinition() && cls != D3D_SVC_OBJECT) { + if (!standardType && recordDecl->isCompleteDefinition() && + cls != D3D_SVC_OBJECT) { // Base types @@ -850,8 +867,8 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, assert(baseType == uint32_t(-1) && "Multiple base types isn't supported in HLSL"); - if (ReflectionError err = GenerateTypeInfo( - baseType, ASTCtx, Refl, qualType, DefaultRowMaj)) + if (ReflectionError err = GenerateTypeInfo(baseType, ASTCtx, Refl, + qualType, DefaultRowMaj)) return err; } } @@ -917,7 +934,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, } } - //Type name + // Type name if (const BuiltinType *bt = dyn_cast(underlying)) { @@ -946,7 +963,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, case BuiltinType::HalfFloat: case BuiltinType::Half: type = D3D_SVT_FLOAT16; - underlyingName = "float16_t"; //TODO: half or float16_t? + underlyingName = "float16_t"; // TODO: half or float16_t? break; case BuiltinType::Short: @@ -1014,7 +1031,8 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, } } - //Turn into proper fully qualified name (e.g. turn vector into float4) + // Turn into proper fully qualified name (e.g. turn vector into + // float4) switch (cls) { @@ -1033,7 +1051,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, break; } - //Insert + // Insert if (Refl.Types.size() >= uint32_t(-1)) return HLSL_REFL_ERR("Type id out of bounds"); @@ -1068,8 +1086,8 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, return err; } - ReflectionVariableTypeSymbol typeSymbol(elementsOrArrayIdDisplay, displayNameId, - underlyingNameId); + ReflectionVariableTypeSymbol typeSymbol(elementsOrArrayIdDisplay, + displayNameId, underlyingNameId); uint32_t i = 0; uint32_t j = uint32_t(Refl.Types.size()); @@ -1095,8 +1113,8 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, DiagnosticsEngine &Diag, QualType Type, uint32_t ArraySizeFlat, ValueDecl *ValDesc, const std::vector &ArraySize, - ReflectionData &Refl, uint32_t AutoBindingSpace, - uint32_t ParentNodeId, bool DefaultRowMaj) { + ReflectionData &Refl, uint32_t AutoBindingSpace, uint32_t ParentNodeId, + bool DefaultRowMaj) { DxcRegisterTypeInfo inputType = GetRegisterTypeInfo(ASTCtx, Type); @@ -1108,9 +1126,8 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, return err; uint32_t arrayId; - - if (ReflectionError err = - Refl.PushArray(arrayId, ArraySizeFlat, ArraySize)) + + if (ReflectionError err = Refl.PushArray(arrayId, ArraySizeFlat, ArraySize)) return err; uint32_t bufferId = 0; @@ -1161,7 +1178,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, uint32_t typeId; - if (ReflectionError err = + if (ReflectionError err = GenerateTypeInfo(typeId, ASTCtx, Refl, innerType, DefaultRowMaj)) return err; @@ -1180,11 +1197,10 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, return ReflectionErrorSuccess; } -template +template [[nodiscard]] ReflectionError -RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, - ReflectionData &Refl, const T &Decls, bool DefaultRowMaj, - uint32_t ParentId) { +RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, ReflectionData &Refl, + const T &Decls, bool DefaultRowMaj, uint32_t ParentId) { for (Decl *decl : Decls) { @@ -1223,10 +1239,9 @@ RecurseBuffer(ASTContext &ASTCtx, const SourceManager &SM, } [[nodiscard]] ReflectionError -RegisterBuffer(uint32_t &bufferId, ASTContext &ASTCtx, - ReflectionData &Refl, const SourceManager &SM, - DeclContext *Buffer, uint32_t NodeId, D3D_CBUFFER_TYPE Type, - bool DefaultRowMaj) { +RegisterBuffer(uint32_t &bufferId, ASTContext &ASTCtx, ReflectionData &Refl, + const SourceManager &SM, DeclContext *Buffer, uint32_t NodeId, + D3D_CBUFFER_TYPE Type, bool DefaultRowMaj) { if (Refl.Buffers.size() >= uint32_t(-1)) return HLSL_REFL_ERR("Buffer id out of bounds"); @@ -1234,7 +1249,7 @@ RegisterBuffer(uint32_t &bufferId, ASTContext &ASTCtx, bufferId = uint32_t(Refl.Buffers.size()); if (ReflectionError err = RecurseBuffer(ASTCtx, SM, Refl, Buffer->decls(), - DefaultRowMaj, NodeId)) + DefaultRowMaj, NodeId)) return err; Refl.Buffers.push_back({Type, NodeId}); @@ -1242,10 +1257,10 @@ RegisterBuffer(uint32_t &bufferId, ASTContext &ASTCtx, return ReflectionErrorSuccess; } -//DxilInterpolationMode.cpp but a little bit cleaned up +// DxilInterpolationMode.cpp but a little bit cleaned up static D3D_INTERPOLATION_MODE GetInterpolationMode(Decl *decl) { - if (!decl) //Return type + if (!decl) // Return type return D3D_INTERPOLATION_UNDEFINED; bool bNoInterpolation = decl->hasAttr(); @@ -1262,7 +1277,7 @@ static D3D_INTERPOLATION_MODE GetInterpolationMode(Decl *decl) { if (mask > 16) return D3D_INTERPOLATION_UNDEFINED; - + static constexpr const D3D_INTERPOLATION_MODE modes[] = { D3D_INTERPOLATION_UNDEFINED, D3D_INTERPOLATION_LINEAR_SAMPLE, @@ -1280,26 +1295,24 @@ static D3D_INTERPOLATION_MODE GetInterpolationMode(Decl *decl) { D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, - D3D_INTERPOLATION_CONSTANT - }; + D3D_INTERPOLATION_CONSTANT}; return modes[mask]; } [[nodiscard]] static ReflectionError AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, - ReflectionData &Refl, - const SourceManager &SM, uint32_t ParentNodeId, - bool DefaultRowMaj) { + ReflectionData &Refl, const SourceManager &SM, + uint32_t ParentNodeId, bool DefaultRowMaj) { uint32_t typeId; - + if (ReflectionError err = GenerateTypeInfo(typeId, ASTCtx, Refl, Type, DefaultRowMaj)) return err; uint32_t nodeId; - + if (ReflectionError err = PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), Decl && dyn_cast(Decl) @@ -1324,18 +1337,18 @@ AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, flags = D3D_PARAMETER_FLAGS(flags | D3D_PF_IN | D3D_PF_OUT); } - Refl.Parameters.push_back( - ReflectionFunctionParameter{typeId, nodeId, uint8_t(interpolationMode), uint8_t(flags)}); + Refl.Parameters.push_back(ReflectionFunctionParameter{ + typeId, nodeId, uint8_t(interpolationMode), uint8_t(flags)}); return ReflectionErrorSuccess; } [[nodiscard]] static ReflectionError RecursiveReflectBody( Stmt *Statement, ASTContext &ASTCtx, DiagnosticsEngine &Diags, - const SourceManager &SM, ReflectionData &Refl, - uint32_t AutoBindingSpace, uint32_t Depth, - D3D12_HLSL_REFLECTION_FEATURE Features, uint32_t ParentNodeId, - bool DefaultRowMaj, std::unordered_map &FwdDecls, + const SourceManager &SM, ReflectionData &Refl, uint32_t AutoBindingSpace, + uint32_t Depth, D3D12_HLSL_REFLECTION_FEATURE Features, + uint32_t ParentNodeId, bool DefaultRowMaj, + std::unordered_map &FwdDecls, const LangOptions &LangOpts, bool SkipNextCompound = false); [[nodiscard]] static ReflectionError GenerateStatement( @@ -1423,7 +1436,8 @@ struct RecursiveStmtReflector : public StmtVisitor { : ASTCtx(ASTCtx), Diags(Diags), SM(SM), Refl(Refl), AutoBindingSpace(AutoBindingSpace), Depth(Depth), Features(Features), ParentNodeId(ParentNodeId), DefaultRowMaj(DefaultRowMaj), - FwdDecls(FwdDecls), LangOpts(LangOpts), SkipNextCompound(SkipNextCompound) {} + FwdDecls(FwdDecls), LangOpts(LangOpts), + SkipNextCompound(SkipNextCompound) {} [[nodiscard]] ReflectionError TraverseStmt(Stmt *S) { @@ -1555,8 +1569,10 @@ struct RecursiveStmtReflector : public StmtVisitor { const SourceRange &sourceRange = varDecl->getSourceRange(); uint32_t nodeId; - if (ReflectionError err = PushNextNodeId(nodeId, Refl, SM, LangOpts, varDecl->getName(), varDecl, - D3D12_HLSL_NODE_TYPE_VARIABLE, ParentNodeId, typeId, &sourceRange, &FwdDecls)) { + if (ReflectionError err = + PushNextNodeId(nodeId, Refl, SM, LangOpts, varDecl->getName(), + varDecl, D3D12_HLSL_NODE_TYPE_VARIABLE, + ParentNodeId, typeId, &sourceRange, &FwdDecls)) { LastError = err; return; } @@ -1602,13 +1618,13 @@ class RecursiveReflector : public DeclVisitor { std::unordered_map &FwdDecls; ReflectionError LastError = ReflectionErrorSuccess; - + [[nodiscard]] ReflectionError PushVariable(ValueDecl *VD, - D3D12_HLSL_NODE_TYPE NodeType) { + D3D12_HLSL_NODE_TYPE NodeType) { uint32_t typeId; if (ReflectionError err = GenerateTypeInfo(typeId, ASTCtx, Refl, - VD->getType(), DefaultRowMaj)) + VD->getType(), DefaultRowMaj)) return err; uint32_t nodeId; @@ -1617,7 +1633,6 @@ class RecursiveReflector : public DeclVisitor { } public: - RecursiveReflector(const DeclContext &Ctx, ASTContext &ASTCtx, const SourceManager &SM, DiagnosticsEngine &Diags, ReflectionData &Refl, uint32_t AutoBindingSpace, @@ -1627,7 +1642,7 @@ class RecursiveReflector : public DeclVisitor { : Ctx(Ctx), ASTCtx(ASTCtx), SM(SM), Diags(Diags), Refl(Refl), AutoBindingSpace(AutoBindingSpace), Depth(Depth), Features(Features), ParentNodeId(ParentNodeId), DefaultRowMaj(DefaultRowMaj), - FwdDecls(FwdDecls){} + FwdDecls(FwdDecls) {} [[nodiscard]] ReflectionError TraverseDeclContext() { @@ -1665,7 +1680,7 @@ class RecursiveReflector : public DeclVisitor { return; uint32_t nodeId; - + if (ReflectionError err = PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), CB->getName(), CB, D3D12_HLSL_NODE_TYPE_REGISTER, @@ -1710,8 +1725,9 @@ class RecursiveReflector : public DeclVisitor { const FunctionDecl *definition = nullptr; uint32_t nodeId; - if (ReflectionError err = PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), FD->getName(), FD, - D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, + if (ReflectionError err = PushNextNodeId( + nodeId, Refl, SM, ASTCtx.getLangOpts(), FD->getName(), FD, + D3D12_HLSL_NODE_TYPE_FUNCTION, ParentNodeId, uint32_t(Refl.Functions.size()), nullptr, &FwdDecls)) { LastError = err; return; @@ -1723,8 +1739,9 @@ class RecursiveReflector : public DeclVisitor { bool hasDefinition = FD->hasBody(definition); ReflectionFunction func; - if (ReflectionError err = ReflectionFunction::Initialize(func, nodeId, FD->getNumParams(), - !FD->getReturnType().getTypePtr()->isVoidType(), hasDefinition)) { + if (ReflectionError err = ReflectionFunction::Initialize( + func, nodeId, FD->getNumParams(), + !FD->getReturnType().getTypePtr()->isVoidType(), hasDefinition)) { LastError = err; return; } @@ -1756,8 +1773,9 @@ class RecursiveReflector : public DeclVisitor { if (!subStmt) continue; - if (ReflectionError err = RecursiveReflectBody(subStmt, ASTCtx, Diags, SM, Refl, AutoBindingSpace, - Depth, Features, nodeId, DefaultRowMaj, FwdDecls, + if (ReflectionError err = RecursiveReflectBody( + subStmt, ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth, + Features, nodeId, DefaultRowMaj, FwdDecls, ASTCtx.getLangOpts())) { LastError = err; return; @@ -1838,43 +1856,43 @@ class RecursiveReflector : public DeclVisitor { void VisitTypedefDecl(TypedefDecl *TD) { - if (LastError) - return; + if (LastError) + return; - if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) - return; + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + return; - uint32_t typeId; - if (ReflectionError err = GenerateTypeInfo( - typeId, ASTCtx, Refl, TD->getUnderlyingType(), DefaultRowMaj)) { - LastError = err; - return; - } + uint32_t typeId; + if (ReflectionError err = GenerateTypeInfo( + typeId, ASTCtx, Refl, TD->getUnderlyingType(), DefaultRowMaj)) { + LastError = err; + return; + } - uint32_t nodeId; - LastError = PushNextNodeId( - nodeId, Refl, SM, ASTCtx.getLangOpts(), TD->getName(), TD, - D3D12_HLSL_NODE_TYPE_TYPEDEF, ParentNodeId, typeId); + uint32_t nodeId; + LastError = + PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), TD->getName(), + TD, D3D12_HLSL_NODE_TYPE_TYPEDEF, ParentNodeId, typeId); } - + void VisitFieldDecl(FieldDecl *FD) { - if (LastError) - return; + if (LastError) + return; - LastError = PushVariable(FD, D3D12_HLSL_NODE_TYPE_VARIABLE); + LastError = PushVariable(FD, D3D12_HLSL_NODE_TYPE_VARIABLE); } void VisitValueDecl(ValueDecl *VD) { - if (LastError) - return; + if (LastError) + return; if (isa(VD)) // Skip parameters, already handled explicitly return; VarDecl *varDecl = dyn_cast(VD); - + if (varDecl && varDecl->hasAttr()) { if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) @@ -1883,27 +1901,27 @@ class RecursiveReflector : public DeclVisitor { LastError = PushVariable(VD, D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE); return; } - + if (varDecl && varDecl->getStorageClass() == StorageClass::SC_Static) { - + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) return; - + LastError = PushVariable(VD, D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE); return; } - + uint32_t arraySize = 1; QualType type = VD->getType(); std::vector arrayElem; - + while (const ConstantArrayType *arr = dyn_cast(type)) { uint32_t current = arr->getSize().getZExtValue(); arrayElem.push_back(current); arraySize *= arr->getSize().getZExtValue(); type = arr->getElementType(); } - + if (!IsHLSLResourceType(type)) { // Handle $Globals or regular variables @@ -1916,13 +1934,13 @@ class RecursiveReflector : public DeclVisitor { return; } - + if (Depth != 0 || !(Features & D3D12_HLSL_REFLECTION_FEATURE_BASICS)) return; - - LastError = FillReflectionRegisterAt(Ctx, ASTCtx, SM, Diags, type, arraySize, VD, - arrayElem, Refl, AutoBindingSpace, ParentNodeId, - DefaultRowMaj); + + LastError = FillReflectionRegisterAt( + Ctx, ASTCtx, SM, Diags, type, arraySize, VD, arrayElem, Refl, + AutoBindingSpace, ParentNodeId, DefaultRowMaj); } void VisitRecordDecl(RecordDecl *RD) { @@ -2023,8 +2041,9 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, uint32_t ParentNodeId, bool DefaultRowMaj, std::unordered_map &FwdDecls) { - RecursiveReflector Reflector(Ctx, ASTCtx, SM, Diags, Refl, AutoBindingSpace, Depth, - Features, ParentNodeId, DefaultRowMaj, FwdDecls); + RecursiveReflector Reflector(Ctx, ASTCtx, SM, Diags, Refl, AutoBindingSpace, + Depth, Features, ParentNodeId, DefaultRowMaj, + FwdDecls); return Reflector.TraverseDeclContext(); } From 8e03ef046bfd53678e2afcbd90c82ae732329e13 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 11 Nov 2025 17:00:54 +0100 Subject: [PATCH 108/126] Moved interpolationMode to node so that struct members can also have interpolation modes as well as function parameters --- .../DxcReflection/DxcReflectionContainer.h | 37 ++++--- .../dxcreflection/dxcreflection_from_ast.cpp | 97 ++++++++++--------- .../tools/dxcreflection/dxcreflector.cpp | 17 ++-- .../DxcReflectionContainer.cpp | 8 +- .../DxcReflectionJson.cpp | 45 +++++---- 5 files changed, 116 insertions(+), 88 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflectionContainer.h b/include/dxc/DxcReflection/DxcReflectionContainer.h index 1fec974530..48ae8bf874 100644 --- a/include/dxc/DxcReflection/DxcReflectionContainer.h +++ b/include/dxc/DxcReflection/DxcReflectionContainer.h @@ -110,8 +110,14 @@ class ReflectionNode { }; }; - uint16_t SemanticId; - uint16_t Padding; + union { + uint32_t SemanticIdInterpolationMode; + struct { + uint16_t SemanticId; + uint8_t InterpolationMode; // D3D_INTERPOLATION_MODE + uint8_t Padding; + }; + }; void SetFwdBck(uint32_t v) { FwdBckHi = v >> 8; @@ -122,12 +128,14 @@ class ReflectionNode { ReflectionNode(D3D12_HLSL_NODE_TYPE NodeType, bool IsFwdDeclare, uint32_t LocalId, uint16_t AnnotationStart, uint32_t ChildCount, uint32_t ParentId, - uint8_t AnnotationCount, uint16_t SemanticId) + uint8_t AnnotationCount, uint16_t SemanticId, + D3D_INTERPOLATION_MODE InterpolationMode) : LocalIdParentLo(LocalId | (ParentId << 24)), ParentHi(ParentId >> 8), Annotations(AnnotationCount), Type(NodeType), ChildCountFwdBckLo(ChildCount | (0xFFu << 24)), AnnotationStart(AnnotationStart), FwdBckHi(0xFFFF), - SemanticId(SemanticId), Padding(0) { + SemanticId(SemanticId), InterpolationMode(InterpolationMode), + Padding(0) { if (IsFwdDeclare) Type |= 0x80; @@ -140,12 +148,16 @@ class ReflectionNode { Initialize(ReflectionNode &OutNode, D3D12_HLSL_NODE_TYPE NodeType, bool IsFwdDeclare, uint32_t LocalId, uint16_t AnnotationStart, uint32_t ChildCount, uint32_t ParentId, uint8_t AnnotationCount, - uint16_t SemanticId) { + uint16_t SemanticId, D3D_INTERPOLATION_MODE InterpolationMode) { if (NodeType < D3D12_HLSL_NODE_TYPE_START || NodeType > D3D12_HLSL_NODE_TYPE_END) return HLSL_REFL_ERR("Invalid NodeType"); + if (InterpolationMode < D3D_INTERPOLATION_UNDEFINED || + InterpolationMode > D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE) + return HLSL_REFL_ERR("Invalid interpolation mode"); + if (LocalId >= ((1u << 24) - 1)) return HLSL_REFL_ERR("LocalId out of bounds"); @@ -159,7 +171,8 @@ class ReflectionNode { return HLSL_REFL_ERR("Fwd declares aren't allowed to have annotations"); OutNode = ReflectionNode(NodeType, IsFwdDeclare, LocalId, AnnotationStart, - ChildCount, ParentId, AnnotationCount, SemanticId); + ChildCount, ParentId, AnnotationCount, SemanticId, + InterpolationMode); return ReflectionErrorSuccess; } @@ -221,6 +234,10 @@ class ReflectionNode { return SemanticId == uint16_t(-1) ? uint32_t(-1) : SemanticId; } + D3D_INTERPOLATION_MODE GetInterpolationMode() const { + return D3D_INTERPOLATION_MODE(InterpolationMode); + } + D3D12_HLSL_NODE_TYPE GetNodeType() const { return D3D12_HLSL_NODE_TYPE(Type & 0x7F); } @@ -248,7 +265,7 @@ class ReflectionNode { ParentHiAnnotationsType32 == other.ParentHiAnnotationsType32 && ChildCountFwdBckLo == other.ChildCountFwdBckLo && AnnotationStartFwdBckHi == other.AnnotationStartFwdBckHi && - SemanticId == other.SemanticId; + SemanticIdInterpolationMode == other.SemanticIdInterpolationMode; } }; @@ -359,13 +376,11 @@ struct ReflectionFunctionParameter { // Mirrors D3D12_PARAMETER_DESC without uint32_t TypeId; uint32_t NodeId; - uint8_t InterpolationMode; // D3D_INTERPOLATION_MODE - uint8_t Flags; // D3D_PARAMETER_FLAGS - uint16_t Padding; + uint32_t Flags; // D3D_PARAMETER_FLAGS bool operator==(const ReflectionFunctionParameter &other) const { return TypeId == other.TypeId && NodeId == other.NodeId && - InterpolationMode == other.InterpolationMode && Flags == other.Flags; + Flags == other.Flags; } }; diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 9e37429df7..e4bb4999a5 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -40,6 +40,49 @@ using namespace clang; namespace hlsl { +// DxilInterpolationMode.cpp but a little bit cleaned up +static D3D_INTERPOLATION_MODE GetInterpolationMode(const Decl *decl) { + + if (!decl) // Return type + return D3D_INTERPOLATION_UNDEFINED; + + bool bNoInterpolation = decl->hasAttr(); + bool bLinear = decl->hasAttr(); + bool bNoperspective = decl->hasAttr(); + bool bCentroid = decl->hasAttr(); + bool bSample = decl->hasAttr(); + + uint8_t mask = uint8_t(bNoInterpolation) << 4; + mask |= uint8_t(bLinear) << 3; + mask |= uint8_t(bNoperspective) << 2; + mask |= uint8_t(bCentroid) << 1; + mask |= uint8_t(bSample); + + if (mask > 16) + return D3D_INTERPOLATION_UNDEFINED; + + static constexpr const D3D_INTERPOLATION_MODE modes[] = { + D3D_INTERPOLATION_UNDEFINED, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_CENTROID, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_LINEAR, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_CENTROID, + D3D_INTERPOLATION_LINEAR_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, + D3D_INTERPOLATION_CONSTANT}; + + return modes[mask]; +} + [[nodiscard]] static ReflectionError PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, const LangOptions &LangOpts, const std::string &UnqualifiedName, @@ -134,6 +177,8 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, } } + D3D_INTERPOLATION_MODE interpolationMode = GetInterpolationMode(DeclSelf); + bool isFwdDeclare = false; bool canHaveFwdDeclare = false; const Decl *fwdDeclare = nullptr; @@ -184,7 +229,7 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, Refl.Nodes.push_back({}); if (ReflectionError err = ReflectionNode::Initialize( Refl.Nodes.back(), Type, isFwdDeclare, LocalId, annotationStart, 0, - ParentNodeId, annotationCount, semanticId)) + ParentNodeId, annotationCount, semanticId, interpolationMode)) return err; if (Refl.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { @@ -1257,49 +1302,6 @@ RegisterBuffer(uint32_t &bufferId, ASTContext &ASTCtx, ReflectionData &Refl, return ReflectionErrorSuccess; } -// DxilInterpolationMode.cpp but a little bit cleaned up -static D3D_INTERPOLATION_MODE GetInterpolationMode(Decl *decl) { - - if (!decl) // Return type - return D3D_INTERPOLATION_UNDEFINED; - - bool bNoInterpolation = decl->hasAttr(); - bool bLinear = decl->hasAttr(); - bool bNoperspective = decl->hasAttr(); - bool bCentroid = decl->hasAttr(); - bool bSample = decl->hasAttr(); - - uint8_t mask = uint8_t(bNoInterpolation) << 4; - mask |= uint8_t(bLinear) << 3; - mask |= uint8_t(bNoperspective) << 2; - mask |= uint8_t(bCentroid) << 1; - mask |= uint8_t(bSample); - - if (mask > 16) - return D3D_INTERPOLATION_UNDEFINED; - - static constexpr const D3D_INTERPOLATION_MODE modes[] = { - D3D_INTERPOLATION_UNDEFINED, - D3D_INTERPOLATION_LINEAR_SAMPLE, - D3D_INTERPOLATION_LINEAR_CENTROID, - D3D_INTERPOLATION_LINEAR_SAMPLE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, - D3D_INTERPOLATION_LINEAR, - D3D_INTERPOLATION_LINEAR_SAMPLE, - D3D_INTERPOLATION_LINEAR_CENTROID, - D3D_INTERPOLATION_LINEAR_SAMPLE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID, - D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE, - D3D_INTERPOLATION_CONSTANT}; - - return modes[mask]; -} - [[nodiscard]] static ReflectionError AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, ReflectionData &Refl, const SourceManager &SM, @@ -1322,7 +1324,6 @@ AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, uint32_t(Refl.Parameters.size()))) return err; - D3D_INTERPOLATION_MODE interpolationMode = GetInterpolationMode(Decl); D3D_PARAMETER_FLAGS flags = D3D_PF_NONE; if (Decl) { @@ -1337,8 +1338,8 @@ AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, flags = D3D_PARAMETER_FLAGS(flags | D3D_PF_IN | D3D_PF_OUT); } - Refl.Parameters.push_back(ReflectionFunctionParameter{ - typeId, nodeId, uint8_t(interpolationMode), uint8_t(flags)}); + Refl.Parameters.push_back( + ReflectionFunctionParameter{typeId, nodeId, uint8_t(flags)}); return ReflectionErrorSuccess; } @@ -2075,7 +2076,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, Result.Nodes.push_back({}); if (ReflectionError err = ReflectionNode::Initialize( Result.Nodes[0], D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, 0, 0, - 0xFFFF, 0, uint16_t(-1))) { + 0xFFFF, 0, uint16_t(-1), D3D_INTERPOLATION_UNDEFINED)) { llvm::errs() << "DxcHLSLReflectionDataFromAST: Failed to add root node: " << err; Result = {}; diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 07146bfee0..3e2de87da1 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -423,15 +423,14 @@ class CHLSLFunctionParameter final : public ID3D12FunctionParameterReflection { m_Data->Parameters[node.GetLocalId()]; const ReflectionVariableType &type = m_Data->Types[param.TypeId]; - *pDesc = - D3D12_PARAMETER_DESC{name, - semanticName, - type.GetType(), - type.GetClass(), - type.GetRows(), - type.GetColumns(), - D3D_INTERPOLATION_MODE(param.InterpolationMode), - D3D_PARAMETER_FLAGS(param.Flags)}; + *pDesc = D3D12_PARAMETER_DESC{name, + semanticName, + type.GetType(), + type.GetClass(), + type.GetRows(), + type.GetColumns(), + node.GetInterpolationMode(), + D3D_PARAMETER_FLAGS(param.Flags)}; return S_OK; } diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index f640bf7d39..3dce2ffed5 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -601,6 +601,11 @@ ReflectionData::Deserialize(const std::vector &Bytes, node.GetSemanticId() >= header.StringsNonDebug) return HLSL_REFL_ERR("Node points to invalid semantic id", i); + if (node.GetInterpolationMode() < D3D_INTERPOLATION_UNDEFINED || + node.GetInterpolationMode() > + D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE) + return HLSL_REFL_ERR("Node has invalid interpolation mode", i); + uint32_t maxValue = 1; bool allowFwdDeclare = false; @@ -874,8 +879,7 @@ ReflectionData::Deserialize(const std::vector &Bytes, Nodes[param.NodeId].GetLocalId() != i || param.TypeId >= header.Types) return HLSL_REFL_ERR("Parameter points to an invalid nodeId", i); - if (param.Flags > 3 || - param.InterpolationMode > D3D_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE) + if (param.Flags > 3) return HLSL_REFL_ERR("Parameter has invalid data", i); } diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index aac363f122..5b2044fa07 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -512,6 +512,21 @@ static void PrintSymbol(JsonWriter &Json, const ReflectionData &Reflection, } } +static void PrintInterpolationMode(JsonWriter &Json, + D3D_INTERPOLATION_MODE Interp) { + + static const char *interpolationModes[] = {"Undefined", + "Constant", + "Linear", + "LinearCentroid", + "LinearNoperspective", + "LinearNoperspectiveCentroid", + "LinearSample", + "LinearNoperspectiveSample"}; + if (Interp) + Json.StringField("Interpolation", interpolationModes[Interp]); +} + // Verbose and all members are slightly different; // Verbose will still print fields even if they aren't relevant, // while all members will not silence important info but that might not matter @@ -552,6 +567,8 @@ static void PrintNode(JsonWriter &Json, const ReflectionData &Reflection, Json.UIntField("SemanticId", node.GetSemanticId()); } + PrintInterpolationMode(Json, node.GetInterpolationMode()); + if (node.GetAnnotationCount()) { if (!Settings.HumanReadable) { @@ -802,8 +819,8 @@ static void PrintType(const ReflectionData &Reflection, uint32_t TypeId, static void PrintParameter(const ReflectionData &Reflection, uint32_t TypeId, bool HasSymbols, JsonWriter &Json, - uint32_t SemanticId, uint8_t InterpolationMode, - uint8_t Flags, + uint32_t SemanticId, + D3D_INTERPOLATION_MODE InterpMode, uint8_t Flags, const ReflectionPrintSettings &Settings) { PrintTypeName(Reflection, TypeId, HasSymbols, Settings, Json, "TypeName"); @@ -825,17 +842,7 @@ static void PrintParameter(const ReflectionData &Reflection, uint32_t TypeId, else if (Flags & D3D_PF_OUT) Json.StringField("Access", "out"); - static const char *interpolationModes[] = {"Undefined", - "Constant", - "Linear", - "LinearCentroid", - "LinearNoperspective", - "LinearNoperspectiveCentroid", - "LinearSample", - "LinearNoperspectiveSample"}; - - if (InterpolationMode) - Json.StringField("Interpolation", interpolationModes[InterpolationMode]); + PrintInterpolationMode(Json, InterpMode); } static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, @@ -886,7 +893,7 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, } PrintParameter(Reflection, param.TypeId, hasSymbols, Json, - node.GetSemanticId(), param.InterpolationMode, + node.GetSemanticId(), node.GetInterpolationMode(), param.Flags, Settings); }); } @@ -906,8 +913,8 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, Json.Object("ReturnType", [&Reflection, &func, &Json, hasSymbols, ¶m, &node, &Settings]() { PrintParameter(Reflection, param.TypeId, hasSymbols, Json, - node.GetSemanticId(), param.InterpolationMode, param.Flags, - Settings); + node.GetSemanticId(), node.GetInterpolationMode(), + param.Flags, Settings); }); } } @@ -1362,9 +1369,11 @@ std::string ReflectionData::ToJson(bool HideFileInfo, json.StringField("ParamName", paramName); + const ReflectionNode &node = Nodes[param.NodeId]; + PrintParameter(*this, param.TypeId, hasSymbols, json, - Nodes[param.NodeId].GetSemanticId(), - param.InterpolationMode, param.Flags, settings); + node.GetSemanticId(), node.GetInterpolationMode(), + param.Flags, settings); } }); From 8ca85cd427ca160ca9a4520d463ac636fe3ea09b Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 11 Nov 2025 20:11:45 +0100 Subject: [PATCH 109/126] Added MuteArgs to fix typedefs printing Args for full types that already receive members --- .../tools/dxcreflectioncontainer/DxcReflectionJson.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 5b2044fa07..0785247caf 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -695,7 +695,8 @@ static void PrintTypeName(const ReflectionData &Reflection, uint32_t TypeId, bool HasSymbols, const ReflectionPrintSettings &Settings, JsonWriter &Json, - const char *NameForTypeName = "Name") { + const char *NameForTypeName = "Name", + bool MuteArgs = false) { if (!Settings.HumanReadable || !HasSymbols) Json.UIntField("TypeId", TypeId); @@ -730,7 +731,7 @@ static void PrintTypeName(const ReflectionData &Reflection, uint32_t TypeId, if (type.GetClass() == D3D_SVC_OBJECT && type.GetType() != D3D_SVT_BYTEADDRESS_BUFFER && type.GetType() != D3D_SVT_RWBYTEADDRESS_BUFFER && - type.GetMemberCount() == 1) { + type.GetMemberCount() == 1 && !MuteArgs) { uint32_t innerTypeId = Reflection.MemberTypeIds[type.GetMemberStart()]; @@ -765,7 +766,7 @@ static void PrintType(const ReflectionData &Reflection, uint32_t TypeId, const ReflectionVariableType &type = Reflection.Types[TypeId]; PrintTypeName(Reflection, TypeId, HasSymbols, Settings, Json, - NameForTypeName); + NameForTypeName, true); if (type.GetBaseClass() != uint32_t(-1)) Json.Object("BaseClass", From 3f0a522882153f4a2c81feb359fbac0756a89c80 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Tue, 11 Nov 2025 23:56:18 +0100 Subject: [PATCH 110/126] Renamed IDxcHLSLReflection to IHLSLReflectionData and IDxcHLSLReflector to IHLSLReflector. Added RunDxReflector (%dxreflector) to the file check to allow properly testing reflection, deserialization & serialization and json output. Added a basic unit test for reflection (resources only). dxreflector.exe now properly outputs to the console without printf, allowing the testing utility and externals to not have to generate a json. --- include/dxc/Test/DxcTestUtils.h | 2 + include/dxc/dxcreflect.h | 33 +- tools/clang/lib/Sema/SemaDeclAttr.cpp | 2 +- .../dxreflector/resource_test.hlsl | 733 ++++++++++++++++++ .../dxcreflection/dxcreflection_from_ast.cpp | 8 +- .../tools/dxcreflection/dxcreflector.cpp | 145 ++-- .../DxcReflectionContainer.cpp | 12 +- .../DxcReflectionJson.cpp | 1 - tools/clang/tools/dxreflector/dxreflector.cpp | 30 +- .../unittests/HLSLTestLib/FileCheckerTest.cpp | 66 ++ 10 files changed, 956 insertions(+), 76 deletions(-) create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/resource_test.hlsl diff --git a/include/dxc/Test/DxcTestUtils.h b/include/dxc/Test/DxcTestUtils.h index 292206d6de..e59303da75 100644 --- a/include/dxc/Test/DxcTestUtils.h +++ b/include/dxc/Test/DxcTestUtils.h @@ -130,6 +130,8 @@ class FileRunCommandPart { LPCWSTR dumpName = nullptr); FileRunCommandResult RunDxc(dxc::DllLoader &DllSupport, const FileRunCommandResult *Prior); + FileRunCommandResult RunDxReflector(dxc::DllLoader &DllSupport, + const FileRunCommandResult *Prior); FileRunCommandResult RunDxv(dxc::DllLoader &DllSupport, const FileRunCommandResult *Prior); FileRunCommandResult RunOpt(dxc::DllLoader &DllSupport, diff --git a/include/dxc/dxcreflect.h b/include/dxc/dxcreflect.h index e90e417316..459b160744 100644 --- a/include/dxc/dxcreflect.h +++ b/include/dxc/dxcreflect.h @@ -212,18 +212,22 @@ DECLARE_INTERFACE_(ID3D12ShaderReflectionType1, ID3D12ShaderReflectionType) { (THIS_ _Out_ D3D12_ARRAY_DESC * pArrayDesc) PURE; }; -typedef interface IDxcHLSLReflection IDxcHLSLReflection; +typedef interface IHLSLReflectionData IHLSLReflectionData; // {7016F834-AE85-4C86-A473-8C2C981DD370} interface DECLSPEC_UUID("7016f834-ae85-4c86-a473-8c2c981dd370") - IDxcHLSLReflection; -DEFINE_GUID(IID_IDxcHLSLReflection, 0x7016f834, 0xae85, 0x4c86, 0xa4, 0x73, + IHLSLReflectionData; +DEFINE_GUID(IID_IHLSLReflectionData, 0x7016f834, 0xae85, 0x4c86, 0xa4, 0x73, 0x8c, 0x2c, 0x98, 0x1d, 0xd3, 0x70); #undef INTERFACE -#define INTERFACE IDxcHLSLReflection +#define INTERFACE IHLSLReflectionData -DECLARE_INTERFACE(IDxcHLSLReflection) { +DECLARE_INTERFACE_(IHLSLReflectionData, IUnknown) { + + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppvObject) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_HLSL_REFLECTION_DESC * pDesc) PURE; @@ -327,6 +331,11 @@ DECLARE_INTERFACE(IDxcHLSLReflection) { (THIS_ _In_ LPCSTR Name, _Outptr_ ID3D12ShaderReflectionType * *ppType) PURE; }; +struct ReflectorFormatSettings { + bool IsHumanReadable; + bool PrintFileInfo; +}; + #undef INTERFACE CLSID_SCOPE const CLSID @@ -336,8 +345,8 @@ CLSID_SCOPE const CLSID 0x435a, {0x16, 0x77, 0xd7, 0xbc, 0xcc, 0xc1}}; -CROSS_PLATFORM_UUIDOF(IDxcHLSLReflector, "ba5a8d8e-bf71-435a-977f-1677d7bcccc1") -struct IDxcHLSLReflector : public IUnknown { +CROSS_PLATFORM_UUIDOF(IHLSLReflector, "ba5a8d8e-bf71-435a-977f-1677d7bcccc1") +struct IHLSLReflector : public IUnknown { virtual HRESULT STDMETHODCALLTYPE FromSource( IDxcBlobEncoding *pSource, @@ -348,13 +357,17 @@ struct IDxcHLSLReflector : public IUnknown { // Defines DxcDefine *pDefines, UINT32 defineCount, // user-provided interface to handle #include directives (optional) - IDxcIncludeHandler *pIncludeHandler, IDxcOperationResult **ppResult) = 0; + IDxcIncludeHandler *pIncludeHandler, IDxcResult **ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE - FromBlob(IDxcBlob *data, IDxcHLSLReflection **ppReflection) = 0; + FromBlob(IDxcBlob *data, IHLSLReflectionData **ppReflection) = 0; - virtual HRESULT STDMETHODCALLTYPE ToBlob(IDxcHLSLReflection *reflection, + virtual HRESULT STDMETHODCALLTYPE ToBlob(IHLSLReflectionData *reflection, IDxcBlob **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE ToString( + IHLSLReflectionData *reflection, ReflectorFormatSettings Settings, + IDxcBlobEncoding **ppResult) = 0; }; #endif diff --git a/tools/clang/lib/Sema/SemaDeclAttr.cpp b/tools/clang/lib/Sema/SemaDeclAttr.cpp index 763f811391..1ffbfe149e 100644 --- a/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -4588,7 +4588,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, //HLSL change, language option to maintain unknown annotations. //This is extremely useful for extending the language for providing extra reflection info. - //These annotations are accessible through IDxcHLSLReflection. + //These annotations are accessible through IHLSLReflectionData. const LangOptions &LangOpts = S.Context.getLangOpts(); diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/resource_test.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/resource_test.hlsl new file mode 100644 index 0000000000..2f0f347975 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/resource_test.hlsl @@ -0,0 +1,733 @@ +// RUN: %dxreflector %s | FileCheck %s + +typedef RWByteAddressBuffer RWBAB; + +RWByteAddressBuffer output0; +RWByteAddressBuffer output1 : SEMA; +RWByteAddressBuffer output2 : register(u1); +RWByteAddressBuffer output3[12]; +RWBAB output4; + +struct Test { + float a; +}; + +typedef float f32; + +typedef StructuredBuffer sbufferFloat; +typedef StructuredBuffer sbufferF32; +typedef StructuredBuffer sbufferTest; + +StructuredBuffer input0; +StructuredBuffer input1; +StructuredBuffer input2; +sbufferFloat input3; +sbufferF32 input4; +sbufferTest input5; + +typedef ByteAddressBuffer BAB; + +ByteAddressBuffer input6; +BAB input7; + +typedef Texture2D t2d; +typedef Texture3D t3d; +typedef TextureCube tcub; +typedef Texture1D t1d; +typedef Texture2DMS t2dms; + +Texture2D input8; +Texture3D input9; +TextureCube input10; +Texture1D input11; +Texture2DMS input12; + +t2d input13; +t3d input14; +tcub input15; +t1d input16; +t2dms input17; + +typedef Texture2D t2duint; + +Texture2D input18; +t2duint input19; + +typedef SamplerState samp; + +SamplerState sampler0; +samp sampler1; + +cbuffer test : register(b0) { float a; }; +cbuffer test2 { float b; }; + +typedef ConstantBuffer cbufTest; + +ConstantBuffer test3; +cbufTest test4; + +float e; + +//TODO: Disable listing this as if it's a struct, but needs a builtin type in DX headers. +typedef RaytracingAccelerationStructure rtas; + +RaytracingAccelerationStructure rtas0; +rtas rtas1; + +[shader("compute")] +[numthreads(16, 16, 1)] +void main(uint id : SV_DispatchThreadID) { } + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "RWBAB", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "RWByteAddressBuffer" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "output0", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "RWByteAddressBuffer" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "output1", +// CHECK: "NodeType": "Register", +// CHECK: "Semantic": "SEMA", +// CHECK: "Register": { +// CHECK: "RegisterType": "RWByteAddressBuffer" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "output2", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "RWByteAddressBuffer" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "output3", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "RWByteAddressBuffer", +// CHECK: "BindCount": 12 +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "output4", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "RWByteAddressBuffer" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f32", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "sbufferFloat", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "StructuredBuffer", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "sbufferF32", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "StructuredBuffer", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "TypeName": "f32", +// CHECK: "UnderlyingName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "sbufferTest", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "StructuredBuffer", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "TypeName": "Test" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input0", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "StructuredBuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input1", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "StructuredBuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32", +// CHECK: "UnderlyingName": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input2", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "StructuredBuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input3", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "StructuredBuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input4", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "StructuredBuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32", +// CHECK: "UnderlyingName": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input5", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "StructuredBuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "BAB", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "ByteAddressBuffer" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input6", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "ByteAddressBuffer" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input7", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "ByteAddressBuffer" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "t2d", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "Texture2D", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "TypeName": "vector", +// CHECK: "UnderlyingName": "float4" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "t3d", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "Texture3D", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "TypeName": "vector", +// CHECK: "UnderlyingName": "float4" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "tcub", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "TextureCube", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "TypeName": "vector", +// CHECK: "UnderlyingName": "float4" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "t1d", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "Texture1D", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "TypeName": "vector", +// CHECK: "UnderlyingName": "float4" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "t2dms", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "Texture2DMS", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input8", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture2D", +// CHECK: "ReturnType": "float", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input9", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture3D", +// CHECK: "ReturnType": "float", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input10", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "TextureCube", +// CHECK: "ReturnType": "float", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input11", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture1D", +// CHECK: "ReturnType": "float", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input12", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture2DMS", +// CHECK: "ReturnType": "float", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input13", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture2D", +// CHECK: "ReturnType": "float", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input14", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture3D", +// CHECK: "ReturnType": "float", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input15", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "TextureCube", +// CHECK: "ReturnType": "float", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input16", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture1D", +// CHECK: "ReturnType": "float", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input17", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture2DMS", +// CHECK: "ReturnType": "float", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "t2duint", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "Texture2D", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "TypeName": "uint4" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input18", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture2D", +// CHECK: "ReturnType": "uint", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "input19", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture2D", +// CHECK: "ReturnType": "uint", +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "samp", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "SamplerState" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "sampler0", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "SamplerState" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "sampler1", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "SamplerState" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "test", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "cbuffer", +// CHECK: "Flags": [ +// CHECK: "UserPacked" +// CHECK: ] +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "test2", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "cbuffer", +// CHECK: "Flags": [ +// CHECK: "UserPacked" +// CHECK: ] +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "cbufTest", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "ConstantBuffer", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "Test", +// CHECK: "TypeName": "Test" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "test3", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "cbuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "test3", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "test4", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "cbuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "test4", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "e", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "rtas", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "RaytracingAccelerationStructure", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "h", +// CHECK: "TypeName": "int" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "rtas0", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "RaytracingAccelerationStructure" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "rtas1", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "RaytracingAccelerationStructure" +// CHECK: } +// CHECK: } +// CHECK: { +// CHECK: "Name": "main", +// CHECK: "NodeType": "Function", +// CHECK: "Annotations": [ +// CHECK: "[shader(\"compute\")]" +// CHECK: ], +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "id": { +// CHECK: "TypeName": "uint", +// CHECK: "Semantic": "SV_DispatchThreadID" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } \ No newline at end of file diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index e4bb4999a5..8184e95ce1 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -2048,7 +2048,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, return Reflector.TraverseDeclContext(); } -[[nodiscard]] ReflectionError DxcHLSLReflectionDataFromAST( +[[nodiscard]] ReflectionError HLSLReflectionDataFromAST( ReflectionData &Result, CompilerInstance &Compiler, TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, D3D12_HLSL_REFLECTION_FEATURE Features, bool DefaultRowMaj) { @@ -2067,7 +2067,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (ReflectionError err = ReflectionNodeSymbol::Initialize( Result.NodeSymbols[0], 0, uint16_t(-1), 0, 0, 0, 0)) { llvm::errs() - << "DxcHLSLReflectionDataFromAST: Failed to add root symbol: " << err; + << "HLSLReflectionDataFromAST: Failed to add root symbol: " << err; Result = {}; return err; } @@ -2077,7 +2077,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (ReflectionError err = ReflectionNode::Initialize( Result.Nodes[0], D3D12_HLSL_NODE_TYPE_NAMESPACE, false, 0, 0, 0, 0xFFFF, 0, uint16_t(-1), D3D_INTERPOLATION_UNDEFINED)) { - llvm::errs() << "DxcHLSLReflectionDataFromAST: Failed to add root node: " + llvm::errs() << "HLSLReflectionDataFromAST: Failed to add root node: " << err; Result = {}; return err; @@ -2088,7 +2088,7 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (ReflectionError err = RecursiveReflectHLSL( Ctx, Compiler.getASTContext(), Diags, SM, Result, AutoBindingSpace, 0, Features, 0, DefaultRowMaj, fwdDecls)) { - llvm::errs() << "DxcHLSLReflectionDataFromAST: Failed: " << err; + llvm::errs() << "HLSLReflectionDataFromAST: Failed: " << err; Result = {}; return err; } diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 3e2de87da1..f347a59d15 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -41,17 +41,23 @@ #include "dxc/Support/dxcapi.impl.h" #include "dxc/Support/dxcfilesystem.h" #include "dxc/dxcapi.internal.h" -#include "dxc/dxcreflect.h" +#include "dxc/dxcreflect.h" #include "dxc/DxcReflection/DxcReflectionContainer.h" +extern "C" const IID IID_IHLSLReflectionData = { + 0x7016f834, + 0xae85, + 0x4c86, + {0xa4, 0x73, 0x8c, 0x2c, 0x98, 0x1d, 0xd3, 0x70}}; + using namespace llvm; using namespace clang; using namespace hlsl; namespace hlsl { -[[nodiscard]] ReflectionError DxcHLSLReflectionDataFromAST( +[[nodiscard]] ReflectionError HLSLReflectionDataFromAST( ReflectionData &Result, clang::CompilerInstance &Compiler, clang::TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, D3D12_HLSL_REFLECTION_FEATURE Features, bool DefaultRowMaj); @@ -513,7 +519,6 @@ class CHLSLReflectionConstantBuffer final return; const std::vector &children = ChildrenNonRecursive.at(NodeId); - const ReflectionShaderResource ® = Data.Registers[node.GetLocalId()]; if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) { @@ -638,10 +643,12 @@ ID3D12ShaderReflectionConstantBuffer *CHLSLReflectionVariable::GetBuffer() { return m_pBuffer; } -struct DxcHLSLReflection : public IDxcHLSLReflection { +struct HLSLReflectionData : public IHLSLReflectionData { ReflectionData Data{}; + std::atomic m_refCount; + std::vector ChildCountsNonRecursive; std::unordered_map> ChildrenNonRecursive; @@ -660,8 +667,9 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { std::vector NodeToParameterId; std::vector FunctionParameters; - DxcHLSLReflection() = default; + HLSLReflectionData() : m_refCount(1) {} + //TODO: This function needs another look definitely void Finalize() { Data.GenerateNameLookupTable(); @@ -690,10 +698,15 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { functionParameters.push_back(i); } - // Filter out fwd declarations for structs, unions, interfaces, functions, + // Filter out backward/fwd declarations for structs, unions, interfaces, functions, // enums - if (!node.IsFwdDeclare()) { + if (node.IsFwdDeclare()) { + ChildCountsNonRecursive[i] = uint32_t(ChildrenNonRecursive[i].size()); + continue; + } + + if (!node.IsFwdDeclare() && node.IsFwdBckDefined()) { FwdDeclType type = FwdDeclType::COUNT; @@ -727,11 +740,7 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { NonFwdIds[int(type)].push_back(typeId); if (hasSymbols) - NameToNonFwdIds[int(type)] - [Data.Strings[Data.NodeSymbols[i].GetNameId()]] = - typeId; - - break; + NameToNonFwdIds[int(type)][Data.NodeIdToFullyResolved[i]] = typeId; } } @@ -781,29 +790,40 @@ struct DxcHLSLReflection : public IDxcHLSLReflection { Data, globalVars, &ConstantBuffers[Data.Buffers.size()], Types); } - DxcHLSLReflection(ReflectionData &&moved) : Data(moved) { Finalize(); } + HLSLReflectionData(ReflectionData &&moved) = delete; + HLSLReflectionData &operator=(HLSLReflectionData &&moved) = delete; - DxcHLSLReflection &operator=(DxcHLSLReflection &&moved) { + // IUnknown + + STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject) override + { + if (!ppvObject) return E_POINTER; - Data = std::move(moved.Data); - ChildCountsNonRecursive = std::move(moved.ChildCountsNonRecursive); - ChildrenNonRecursive = std::move(moved.ChildrenNonRecursive); - ConstantBuffers = std::move(moved.ConstantBuffers); - NameToConstantBuffers = std::move(moved.NameToConstantBuffers); - Types = std::move(moved.Types); + if (riid == IID_IUnknown || riid == IID_IHLSLReflectionData) + { + *ppvObject = static_cast(this); + AddRef(); + return S_OK; + } - for (int i = 0; i < int(FwdDeclType::COUNT); ++i) { - NonFwdIds[i] = std::move(moved.NonFwdIds[i]); - NameToNonFwdIds[i] = std::move(moved.NameToNonFwdIds[i]); - } + *ppvObject = nullptr; + return E_NOINTERFACE; + } - NodeToParameterId = std::move(moved.NodeToParameterId); - FunctionParameters = std::move(moved.FunctionParameters); + STDMETHOD_(ULONG, AddRef)() override + { + return ++m_refCount; + } - return *this; + STDMETHOD_(ULONG, Release)() override { + ULONG count = --m_refCount; + if (!count) + delete this; + return count; } - // Conversion of DxcHLSL structs to D3D12_HLSL standardized structs + + // Conversion of IReflection structs to D3D12_HLSL standardized structs STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_HLSL_REFLECTION_DESC *pDesc) override { @@ -1577,19 +1597,14 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, ReflectionData refl; - if (ReflectionError err = DxcHLSLReflectionDataFromAST( + if (ReflectionError err = HLSLReflectionDataFromAST( refl, astHelper.compiler, *astHelper.tu, opts.AutoBindingSpace, reflectMask, opts.DefaultRowMajor)) { - fprintf(stderr, "DxcHLSLReflectionDataFromAST failed %s\n", + fprintf(stderr, "HLSLReflectionDataFromAST failed %s\n", err.toString().c_str()); return E_FAIL; } - bool hideFileInfo = !opts.ReflOpt.ShowFileInfo; - bool humanFriendly = !opts.ReflOpt.ShowRawData; - - printf("%s\n", refl.ToJson(hideFileInfo, humanFriendly).c_str()); - // Debug: Verify deserialization, otherwise print error. #ifndef NDEBUG @@ -1642,7 +1657,7 @@ HRESULT GetFromSource(DxcLangExtensionsHelper *pHelper, LPCSTR pFileName, HRESULT ReadOptsAndValidate(hlsl::options::MainArgs &mainArgs, hlsl::options::DxcOpts &opts, - IDxcOperationResult **ppResult) { + IDxcResult **ppResult) { const llvm::opt::OptTable *table = ::options::getHlslOptTable(); CComPtr pOutputStream; @@ -1667,7 +1682,7 @@ HRESULT ReadOptsAndValidate(hlsl::options::MainArgs &mainArgs, } } // namespace -class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { +class DxcReflector : public IHLSLReflector, public IDxcLangExtensions3 { private: DXC_MICROCOM_TM_REF_FIELDS() DxcLangExtensionsHelper m_langExtensionsHelper; @@ -1679,7 +1694,7 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) override { - return DoBasicQueryInterface( this, iid, ppvObject); } @@ -1693,8 +1708,7 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { // Defines DxcDefine *pDefines, UINT32 defineCount, // user-provided interface to handle #include directives (optional) - IDxcIncludeHandler *pIncludeHandler, - IDxcOperationResult **ppResult) override { + IDxcIncludeHandler *pIncludeHandler, IDxcResult **ppResult) override { if (pSource == nullptr || ppResult == nullptr || (argCount > 0 && pArguments == nullptr) || @@ -1745,10 +1759,18 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { errors, rewrite, msfPtr, reflection); std::vector Bytes; + std::string json; + + if (SUCCEEDED(status)) { - if (SUCCEEDED(status)) reflection.Dump(Bytes); + bool hideFileInfo = !opts.ReflOpt.ShowFileInfo; + bool humanFriendly = !opts.ReflOpt.ShowRawData; + + json = reflection.ToJson(hideFileInfo, humanFriendly); + } + return DxcResult::Create( status, DXC_OUT_OBJECT, {DxcOutputObject::ObjectOutput(Bytes.data(), Bytes.size()), @@ -1760,7 +1782,7 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { } HRESULT STDMETHODCALLTYPE - FromBlob(IDxcBlob *data, IDxcHLSLReflection **ppReflection) override { + FromBlob(IDxcBlob *data, IHLSLReflectionData **ppReflection) override { if (!data || !data->GetBufferSize() || !ppReflection) return E_POINTER; @@ -1769,35 +1791,64 @@ class DxcReflector : public IDxcHLSLReflector, public IDxcLangExtensions3 { (const std::byte *)data->GetBufferPointer() + data->GetBufferSize()); + HLSLReflectionData *reflectData = new HLSLReflectionData(); + *ppReflection = reflectData; + try { - ReflectionData deserial; - if (ReflectionError err = deserial.Deserialize(bytes, true)) + if (ReflectionError err = reflectData->Data.Deserialize(bytes, true)) { + delete reflectData; + *ppReflection = nullptr; + fprintf(stderr, "Couldn't deserialize: %s\n", err.toString().c_str()); return E_FAIL; + } + reflectData->Finalize(); - *ppReflection = new DxcHLSLReflection(std::move(deserial)); return S_OK; } catch (...) { + delete reflectData; + *ppReflection = nullptr; return E_FAIL; } } - HRESULT STDMETHODCALLTYPE ToBlob(IDxcHLSLReflection *reflection, + HRESULT STDMETHODCALLTYPE ToBlob(IHLSLReflectionData *reflection, IDxcBlob **ppResult) override { if (!reflection || !ppResult) return E_POINTER; - DxcHLSLReflection *refl = dynamic_cast(reflection); + HLSLReflectionData *refl = dynamic_cast(reflection); if (!refl) return E_UNEXPECTED; + DxcThreadMalloc TM(m_pMalloc); + std::vector bytes; refl->Data.Dump(bytes); return DxcCreateBlobOnHeapCopy(bytes.data(), bytes.size(), ppResult); } + + HRESULT STDMETHODCALLTYPE ToString(IHLSLReflectionData *reflection, + ReflectorFormatSettings Settings, + IDxcBlobEncoding **ppResult) override { + + if (!reflection || !ppResult) + return E_POINTER; + + HLSLReflectionData *refl = dynamic_cast(reflection); + + if (!refl) + return E_UNEXPECTED; + + DxcThreadMalloc TM(m_pMalloc); + std::string str = refl->Data.ToJson(!Settings.PrintFileInfo, Settings.IsHumanReadable); + + return DxcCreateBlob(str.c_str(), str.size(), false, true, true, + CP_UTF8, DxcGetThreadMallocNoRef(), ppResult); + } }; HRESULT CreateDxcReflector(REFIID riid, LPVOID *ppv) { diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index 3dce2ffed5..f76d3648eb 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -165,7 +165,7 @@ ReflectionData::RegisterTypeList(const std::vector &TypeIds, return ReflectionErrorSuccess; } -struct DxcHLSLHeader { +struct HLSLReflectionDataHeader { uint32_t MagicNumber; uint16_t Version; @@ -467,7 +467,7 @@ bool ReflectionData::GenerateNameLookupTable() { void ReflectionData::Dump(std::vector &Bytes) const { - uint64_t toReserve = sizeof(DxcHLSLHeader); + uint64_t toReserve = sizeof(HLSLReflectionDataHeader); Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, @@ -478,7 +478,7 @@ void ReflectionData::Dump(std::vector &Bytes) const { toReserve = 0; - UnsafeCast(Bytes, + UnsafeCast(Bytes, toReserve) = {ReflectionDataMagic, ReflectionDataVersion, uint16_t(Sources.size()), @@ -500,7 +500,7 @@ void ReflectionData::Dump(std::vector &Bytes) const { uint32_t(Parameters.size()), uint32_t(Statements.size())}; - toReserve += sizeof(DxcHLSLHeader); + toReserve += sizeof(HLSLReflectionDataHeader); Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, @@ -537,8 +537,8 @@ ReflectionData::Deserialize(const std::vector &Bytes, *this = {}; uint64_t off = 0; - DxcHLSLHeader header; - if (ReflectionError err = Consume(Bytes, off, header)) + HLSLReflectionDataHeader header; + if (ReflectionError err = Consume(Bytes, off, header)) return err; if (header.MagicNumber != ReflectionDataMagic) diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 0785247caf..82b7e23c9f 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -1472,7 +1472,6 @@ std::string ReflectionData::ToJson(bool HideFileInfo, else PrintChildren(*this, json, "Children", 1, Nodes.size(), settings); } - return json.str(); } diff --git a/tools/clang/tools/dxreflector/dxreflector.cpp b/tools/clang/tools/dxreflector/dxreflector.cpp index 4852f1b452..0b848722e2 100644 --- a/tools/clang/tools/dxreflector/dxreflector.cpp +++ b/tools/clang/tools/dxreflector/dxreflector.cpp @@ -162,8 +162,8 @@ int main(int argc, const char **argv) { return 0; } - CComPtr pReflector; - CComPtr pRewriteResult; + CComPtr pReflector; + CComPtr pReflectionResult; CComPtr pSource; std::wstring wName(CA2W(dxreflectorOpts.InputFile.empty() ? "" @@ -190,21 +190,37 @@ int main(int argc, const char **argv) { IFT(pReflector->FromSource(pSource, wName.c_str(), wargsC.data(), uint32_t(wargsC.size()), nullptr, 0, - pIncludeHandler, &pRewriteResult)); + pIncludeHandler, &pReflectionResult)); if (dxreflectorOpts.OutputObject.empty()) { + // No -Fo, print to console - WriteOperationResultToConsole(pRewriteResult, + + CComPtr pJson; + CComPtr pReflectionBlob; + CComPtr pReflectionData; + + ReflectorFormatSettings formatSettings{}; + formatSettings.PrintFileInfo = dxreflectorOpts.ReflOpt.ShowFileInfo; + formatSettings.IsHumanReadable = !dxreflectorOpts.ReflOpt.ShowRawData; + + IFT(pReflectionResult->GetResult(&pReflectionBlob)); + IFT(pReflector->FromBlob(pReflectionBlob, &pReflectionData)); + IFT(pReflector->ToString(pReflectionData, formatSettings, &pJson)); + + WriteBlobToConsole(pJson, STD_OUTPUT_HANDLE); + + WriteOperationResultToConsole(pReflectionResult, !dxreflectorOpts.OutputWarnings); } else { - WriteOperationErrorsToConsole(pRewriteResult, + WriteOperationErrorsToConsole(pReflectionResult, !dxreflectorOpts.OutputWarnings); HRESULT hr; - IFT(pRewriteResult->GetStatus(&hr)); + IFT(pReflectionResult->GetStatus(&hr)); if (SUCCEEDED(hr)) { CA2W wOutputObject(dxreflectorOpts.OutputObject.data()); CComPtr pObject; - IFT(pRewriteResult->GetResult(&pObject)); + IFT(pReflectionResult->GetResult(&pObject)); WriteBlobToFile(pObject, wOutputObject.m_psz, dxreflectorOpts.DefaultTextCodePage); } diff --git a/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp b/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp index e4e8936d21..df2e016a9c 100644 --- a/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp +++ b/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp @@ -48,6 +48,8 @@ #include "dxc/Test/D3DReflectionDumper.h" #include "dxc/Test/RDATDumper.h" +#include "dxc/dxcreflect.h" + using namespace hlsl::dump; using namespace std; @@ -98,6 +100,8 @@ FileRunCommandPart::Run(dxc::DllLoader &DllSupport, return RunDxilVer(DllSupport, Prior); } else if (0 == _stricmp(Command.c_str(), "%dxc")) { return RunDxc(DllSupport, Prior); + } else if (0 == _stricmp(Command.c_str(), "%dxreflector")) { + return RunDxReflector(DllSupport, Prior); } else if (0 == _stricmp(Command.c_str(), "%dxv")) { return RunDxv(DllSupport, Prior); } else if (0 == _stricmp(Command.c_str(), "%opt")) { @@ -598,6 +602,68 @@ FileRunCommandPart::RunDxc(dxc::DllLoader &DllSupport, return result; } +FileRunCommandResult +FileRunCommandPart::RunDxReflector(dxc::DllLoader &DllSupport, + const FileRunCommandResult *Prior) { + // Support piping stdin from prior if needed. + UNREFERENCED_PARAMETER(Prior); + hlsl::options::MainArgs args; + hlsl::options::DxcOpts opts; + FileRunCommandResult readOptsResult = ReadOptsForDxc(args, opts); + if (readOptsResult.ExitCode) + return readOptsResult; + + std::vector flags; + + std::vector argWStrings; + CopyArgsToWStrings(opts.Args, hlsl::options::ReflectOption, argWStrings); + for (const std::wstring &a : argWStrings) + flags.push_back(a.data()); + + CComPtr pLibrary; + CComPtr pReflector; + CComPtr pResult; + CComPtr pSource; + CComPtr pJson; + CComPtr pReflectionBlob; + CComPtr pReflectionData; + + ReflectorFormatSettings formatSettings{}; + formatSettings.PrintFileInfo = opts.ReflOpt.ShowFileInfo; + formatSettings.IsHumanReadable = !opts.ReflOpt.ShowRawData; + + HRESULT resultStatus; + + IFT(DllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary)); + IFT(pLibrary->CreateBlobFromFile(CommandFileName, nullptr, &pSource)); + CComPtr pIncludeHandler = + AllocVFSIncludeHandler(pLibrary, pVFS); + IFT(DllSupport.CreateInstance(CLSID_DxcReflector, &pReflector)); + IFT(pReflector->FromSource(pSource, CommandFileName, flags.data(), + flags.size(), nullptr, 0, pIncludeHandler, + &pResult)); + IFT(pResult->GetStatus(&resultStatus)); + + FileRunCommandResult result = {}; + if (SUCCEEDED(resultStatus)) { + IFT(pResult->GetResult(&pReflectionBlob)); + IFT(pReflector->FromBlob(pReflectionBlob, &pReflectionData)); + IFT(pReflector->ToString(pReflectionData, formatSettings, &pJson)); + result.StdOut = BlobToUtf8(pJson); + CComPtr pStdErr; + IFT(pResult->GetErrorBuffer(&pStdErr)); + result.StdErr = BlobToUtf8(pStdErr); + result.ExitCode = 0; + } else { + IFT(pResult->GetErrorBuffer(&pJson)); + result.StdErr = BlobToUtf8(pJson); + result.ExitCode = resultStatus; + } + + result.OpResult = pResult; + return result; +} + FileRunCommandResult FileRunCommandPart::RunDxv(dxc::DllLoader &DllSupport, const FileRunCommandResult *Prior) { From 66fa2051b936020d64010c1986b671dcdecefba8 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 12 Nov 2025 13:42:35 +0100 Subject: [PATCH 111/126] Added forward declare test. Added requirement from structs that it has to have members; which is true in C but not C++/HLSL. Fixed issue with dxreflector.exe if the HLSL is invalid and no -Fo is used. --- .../dxreflector/fwd_declare_test.hlsl | 187 ++++++++++++++++++ .../DxcReflectionContainer.cpp | 4 - tools/clang/tools/dxreflector/dxreflector.cpp | 17 +- 3 files changed, 198 insertions(+), 10 deletions(-) create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/fwd_declare_test.hlsl diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/fwd_declare_test.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/fwd_declare_test.hlsl new file mode 100644 index 0000000000..957f49a0ab --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/fwd_declare_test.hlsl @@ -0,0 +1,187 @@ +// RUN: %dxreflector %s | FileCheck %s + +namespace tst { + struct Tst; + struct A { + float a(); + }; +} + +struct Test; +struct Test; + +struct Never0; + +struct A { + float a; + float t(Test t); + float t2(tst::Tst a); + float neverDeclared(Never0 a); +}; + +struct Test { + float a; +}; + +struct tst::Tst { + float a; +}; + +float A::t(Test t) { return 2; } +float A::t2(tst::Tst a) { return 2; } +float tst::A::a() { return 2; } + +float neverDeclared(Never0 a); + +float4 test(); +float4 test(); + +float4 test() { return 0.xxxx; } + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "tst", +// CHECK: "NodeType": "Namespace", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "Tst", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "A", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Never0", +// CHECK: "NodeType": "Struct" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "A", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "t", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "t": { +// CHECK: "TypeName": "Test" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "t2", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "a": { +// CHECK: "TypeName": "tst::Tst" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "neverDeclared", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "HasDefinition": false, +// CHECK: "Params": { +// CHECK: "a": { +// CHECK: "TypeName": "Never0" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "neverDeclared", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "HasDefinition": false, +// CHECK: "Params": { +// CHECK: "a": { +// CHECK: "TypeName": "Never0" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "test", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index f76d3648eb..42665aba81 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -1024,10 +1024,6 @@ ReflectionData::Deserialize(const std::vector &Bytes, break; case D3D_SVC_STRUCT: - - if (!type.GetMemberCount()) - return HLSL_REFL_ERR("Type (struct) is missing children", i); - [[fallthrough]]; case D3D_SVC_INTERFACE_CLASS: diff --git a/tools/clang/tools/dxreflector/dxreflector.cpp b/tools/clang/tools/dxreflector/dxreflector.cpp index 0b848722e2..16f8c6aee9 100644 --- a/tools/clang/tools/dxreflector/dxreflector.cpp +++ b/tools/clang/tools/dxreflector/dxreflector.cpp @@ -204,14 +204,19 @@ int main(int argc, const char **argv) { formatSettings.PrintFileInfo = dxreflectorOpts.ReflOpt.ShowFileInfo; formatSettings.IsHumanReadable = !dxreflectorOpts.ReflOpt.ShowRawData; - IFT(pReflectionResult->GetResult(&pReflectionBlob)); - IFT(pReflector->FromBlob(pReflectionBlob, &pReflectionData)); - IFT(pReflector->ToString(pReflectionData, formatSettings, &pJson)); - - WriteBlobToConsole(pJson, STD_OUTPUT_HANDLE); - WriteOperationResultToConsole(pReflectionResult, !dxreflectorOpts.OutputWarnings); + + HRESULT hr; + IFT(pReflectionResult->GetStatus(&hr)); + + if(SUCCEEDED(hr)) { + IFT(pReflectionResult->GetResult(&pReflectionBlob)); + IFT(pReflector->FromBlob(pReflectionBlob, &pReflectionData)); + IFT(pReflector->ToString(pReflectionData, formatSettings, &pJson)); + WriteBlobToConsole(pJson, STD_OUTPUT_HANDLE); + } + } else { WriteOperationErrorsToConsole(pReflectionResult, !dxreflectorOpts.OutputWarnings); From e1a8ebfb71c99ca29946a6544f0cdc503adc6842 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 12 Nov 2025 16:46:48 +0100 Subject: [PATCH 112/126] Fixed underlying array sizes being mixed up. Added unit test for all sorts of array sizes. Added unit test for 'empty' hlsl files --- .../HLSLFileCheck/dxreflector/array_test.hlsl | 908 ++++++++++++++++++ .../dxreflector/relatively_empty.hlsl | 14 + .../dxcreflection/dxcreflection_from_ast.cpp | 52 +- 3 files changed, 965 insertions(+), 9 deletions(-) create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/array_test.hlsl create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/relatively_empty.hlsl diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/array_test.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/array_test.hlsl new file mode 100644 index 0000000000..f6ee17f6a1 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/array_test.hlsl @@ -0,0 +1,908 @@ +// RUN: %dxreflector %s | FileCheck %s + +typedef float farr4[4]; +typedef float farr4x3[4][3]; +typedef float farr4x3x5[4][3][5]; + +typedef farr4 farr4a6[6]; +typedef farr4x3 farr4x3a6a7[6][7]; +typedef farr4x3x5 farr4x3x5a6a7a8[6][7][8]; + +typedef float f32; + +typedef f32 f32arr4[4]; +typedef f32 f32arr4x3[4][3]; +typedef f32 f32arr4x3x5[4][3][5]; + +typedef f32arr4 f32arr4a6[6]; +typedef f32arr4x3 f32arr4x3a6a7[6][7]; +typedef f32arr4x3x5 f32arr4x3x5a6a7a8[6][7][8]; + +farr4 arr0[2]; +farr4x3 arr1[2]; +farr4x3x5 arr2[2]; + +farr4a6 arr3[2]; +farr4x3a6a7 arr4[2]; +farr4x3x5a6a7a8 arr5[2]; + +f32arr4 arr6[2]; +f32arr4x3 arr7[2]; +f32arr4x3x5 arr8[2]; + +f32arr4a6 arr9[2]; +f32arr4x3a6a7 arr10[2]; +f32arr4x3x5a6a7a8 arr11[2]; + +struct Test { + + farr4 arr0[2]; + farr4x3 arr1[2]; + farr4x3x5 arr2[2]; + + farr4a6 arr3[2]; + farr4x3a6a7 arr4[2]; + farr4x3x5a6a7a8 arr5[2]; + + f32arr4 arr6[2]; + f32arr4x3 arr7[2]; + f32arr4x3x5 arr8[2]; + + f32arr4a6 arr9[2]; + f32arr4x3a6a7 arr10[2]; + f32arr4x3x5a6a7a8 arr11[2]; +}; + +void func( + Test t[2], + farr4 arr0[2], + farr4x3 arr1[2], + farr4x3x5 arr2[2], + farr4a6 arr3[2], + farr4x3a6a7 arr4[2], + farr4x3x5a6a7a8 arr5[2], + f32arr4 arr6[2], + f32arr4x3 arr7[2], + f32arr4x3x5 arr8[2], + f32arr4a6 arr9[2], + f32arr4x3a6a7 arr10[2], + f32arr4x3x5a6a7a8 arr11[2]) { } + +Texture2D tex0[4]; +Texture2D tex1[4][3]; +Texture2D tex2[4][3][2]; + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "farr4", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "float", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "farr4x3", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "float", +// CHECK: "ArraySize": [ +// CHECK: 4, +// CHECK: 3 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "farr4x3x5", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "float", +// CHECK: "ArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "farr4a6", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "farr4", +// CHECK: "ArraySize": [ +// CHECK: 6 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 6 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "farr4x3a6a7", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "farr4x3", +// CHECK: "ArraySize": [ +// CHECK: 6, +// CHECK: 7 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 6, +// CHECK: 7 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "farr4x3x5a6a7a8", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "farr4x3x5", +// CHECK: "ArraySize": [ +// CHECK: 6, +// CHECK: 7, +// CHECK: 8 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 6, +// CHECK: 7, +// CHECK: 8 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f32", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f32arr4", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "f32", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ], +// CHECK: "UnderlyingName": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f32arr4x3", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "f32", +// CHECK: "ArraySize": [ +// CHECK: 4, +// CHECK: 3 +// CHECK: ], +// CHECK: "UnderlyingName": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f32arr4x3x5", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "f32", +// CHECK: "ArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5 +// CHECK: ], +// CHECK: "UnderlyingName": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f32arr4a6", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4", +// CHECK: "ArraySize": [ +// CHECK: 6 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 6 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f32arr4x3a6a7", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4x3", +// CHECK: "ArraySize": [ +// CHECK: 6, +// CHECK: 7 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 6, +// CHECK: 7 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f32arr4x3x5a6a7a8", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4x3x5", +// CHECK: "ArraySize": [ +// CHECK: 6, +// CHECK: 7, +// CHECK: 8 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 6, +// CHECK: 7, +// CHECK: 8 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr0", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr1", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4x3", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr2", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4x3x5", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr3", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4a6", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 6, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr4", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4x3a6a7", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 6, +// CHECK: 7, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr5", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4x3x5a6a7a8", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 6, +// CHECK: 7, +// CHECK: 8, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr6", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr7", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4x3", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr8", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4x3x5", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr9", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4a6", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 6, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr10", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4x3a6a7", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 6, +// CHECK: 7, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr11", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4x3x5a6a7a8", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 6, +// CHECK: 7, +// CHECK: 8, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "arr0", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr1", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4x3", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr2", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4x3x5", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr3", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4a6", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 6, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr4", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4x3a6a7", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 6, +// CHECK: 7, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr5", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "farr4x3x5a6a7a8", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 6, +// CHECK: 7, +// CHECK: 8, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr6", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr7", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4x3", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr8", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4x3x5", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr9", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4a6", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 6, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr10", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4x3a6a7", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 6, +// CHECK: 7, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "arr11", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "f32arr4x3x5a6a7a8", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 6, +// CHECK: 7, +// CHECK: 8, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "func", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "t": { +// CHECK: "TypeName": "Test", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr0": { +// CHECK: "TypeName": "farr4", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr1": { +// CHECK: "TypeName": "farr4x3", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr2": { +// CHECK: "TypeName": "farr4x3x5", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr3": { +// CHECK: "TypeName": "farr4a6", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 6, +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr4": { +// CHECK: "TypeName": "farr4x3a6a7", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 6, +// CHECK: 7, +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr5": { +// CHECK: "TypeName": "farr4x3x5a6a7a8", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 6, +// CHECK: 7, +// CHECK: 8, +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr6": { +// CHECK: "TypeName": "f32arr4", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr7": { +// CHECK: "TypeName": "f32arr4x3", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr8": { +// CHECK: "TypeName": "f32arr4x3x5", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr9": { +// CHECK: "TypeName": "f32arr4a6", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 6, +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr10": { +// CHECK: "TypeName": "f32arr4x3a6a7", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 6, +// CHECK: 7, +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "arr11": { +// CHECK: "TypeName": "f32arr4x3x5a6a7a8", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 5, +// CHECK: 6, +// CHECK: 7, +// CHECK: 8, +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "tex0", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture2D", +// CHECK: "ReturnType": "float", +// CHECK: "BindCount": 4, +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "tex1", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture2D", +// CHECK: "ReturnType": "float", +// CHECK: "BindCount": 12, +// CHECK: "ArraySize": [ +// CHECK: 4, +// CHECK: 3 +// CHECK: ], +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "tex2", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "Texture", +// CHECK: "Dimension": "Texture2D", +// CHECK: "ReturnType": "float", +// CHECK: "BindCount": 24, +// CHECK: "ArraySize": [ +// CHECK: 4, +// CHECK: 3, +// CHECK: 2 +// CHECK: ], +// CHECK: "Flags": [ +// CHECK: "TextureComponent0", +// CHECK: "TextureComponent1" +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/relatively_empty.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/relatively_empty.hlsl new file mode 100644 index 0000000000..de6e2672cf --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/relatively_empty.hlsl @@ -0,0 +1,14 @@ +// RUN: %dxreflector %s | FileCheck %s + +#define EMPTY + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ] +// CHECK: } diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 8184e95ce1..0a22764d5a 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -575,6 +575,44 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, return GetTextureRegisterInfo(ASTCtx, typeName, isWrite, recordDecl); } +// Collect array sizes in the logical order (inner dims first, then outer). +// Example: +// F32[4][3] -> {4, 3} +// typedef T = F32[4][3]; +// T[2] -> {4, 3, 2} +[[nodiscard]] static ReflectionError +CollectUnderlyingArraySizes(QualType &T, std::vector &Out, + uint64_t &FlatSize) { + + T = T.getNonReferenceType(); + + std::vector local; + + while (const ConstantArrayType *arr = dyn_cast(T)) { + + uint64_t siz = arr->getSize().getZExtValue(); + FlatSize *= siz; + + if ((FlatSize >> 32) || (siz >> 32)) + return HLSL_REFL_ERR("Can't calculate flat array size: out of bits"); + + local.push_back(uint32_t(siz)); + T = arr->getElementType().getNonReferenceType(); + } + + if (const TypedefType *td = dyn_cast(T)) { + + T = td->getDecl()->getUnderlyingType().getNonReferenceType(); + + if (T->isArrayType()) + if (ReflectionError err = CollectUnderlyingArraySizes(T, Out, FlatSize)) + return err; + } + + Out.insert(Out.end(), local.begin(), local.end()); + return ReflectionErrorSuccess; +} + [[nodiscard]] ReflectionError GenerateTypeInfo(uint32_t &TypeId, ASTContext &ASTCtx, ReflectionData &Refl, QualType Original, bool DefaultRowMaj) { @@ -585,17 +623,13 @@ GenerateTypeInfo(uint32_t &TypeId, ASTContext &ASTCtx, ReflectionData &Refl, // then we want to maintain sugared name + array info (of sugar) for // reflection but for low level type info, we would want to know float4[4] - uint32_t arraySizeUnderlying = 1; - QualType underlying = Original.getNonReferenceType().getCanonicalType(); + uint64_t arraySizeUnderlying = 1; std::vector arrayElemUnderlying; - while (const ConstantArrayType *arr = - dyn_cast(underlying)) { - uint32_t current = arr->getSize().getZExtValue(); - arrayElemUnderlying.push_back(current); - arraySizeUnderlying *= arr->getSize().getZExtValue(); - underlying = arr->getElementType().getNonReferenceType().getCanonicalType(); - } + QualType underlying = Original; + if (ReflectionError err = CollectUnderlyingArraySizes( + underlying, arrayElemUnderlying, arraySizeUnderlying)) + return err; uint32_t arraySizeDisplay = 1; std::vector arrayElemDisplay; From 6a1b3ee245e4114b05ac3cc31c9a076ec591f828 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 12 Nov 2025 21:06:53 +0100 Subject: [PATCH 113/126] Added tests for enums, recursive buffers, variable types, stripping symbols, inheritance and functions/annotations/(in)(out)/interpolationMode. Fixed variable names of structs when stripping symbols --- .../test/HLSLFileCheck/dxreflector/enums.hlsl | 553 ++++++++++++++++++ .../functions_semantics_interpolation.hlsl | 125 ++++ .../dxreflector/inheritance.hlsl | 194 ++++++ .../dxreflector/recursive_buffer.hlsl | 268 +++++++++ .../dxreflector/stripped_variable_types.hlsl | 306 ++++++++++ .../dxreflector/variable_types.hlsl | 92 +++ .../DxcReflectionJson.cpp | 2 +- 7 files changed, 1539 insertions(+), 1 deletion(-) create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/enums.hlsl create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/functions_semantics_interpolation.hlsl create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/inheritance.hlsl create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/recursive_buffer.hlsl create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/stripped_variable_types.hlsl create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/variable_types.hlsl diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/enums.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/enums.hlsl new file mode 100644 index 0000000000..002f6ac67d --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/enums.hlsl @@ -0,0 +1,553 @@ +// RUN: %dxreflector -T lib_6_4 -enable-16bit-types %s | FileCheck %s + +enum Test { + Test_A, + Test_B, + Test_C +}; + +enum class Test2 { + A, + B, + C +}; + +enum class Test3 : int { + A, + B, + C +}; + +enum class Test4 : uint64_t { + A, + B, + C +}; + +enum class Test5 : int64_t { + A, + B, + C +}; + +enum class Test6 : uint { + A, + B, + C +}; + +enum class Test7 : int16_t { + A, + B, + C +}; + +enum class Test8 : uint16_t { + A, + B, + C +}; + +Test a; +Test2 b; +Test3 c; +Test4 d; +Test5 e; +Test6 f; +Test7 g; +Test8 h; + +struct A { + Test a; + Test2 b; + Test3 c; + Test4 d; + Test5 e; + Test6 f; + Test7 g; + Test8 h; +}; + +StructuredBuffer sbuf; + +void test( + Test a, + Test2 b, + Test3 c, + Test4 d, + Test5 e, + Test6 f, + Test7 g, + Test8 h) {} + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "Test", +// CHECK: "NodeType": "Enum", +// CHECK: "Enum": { +// CHECK: "Name": "Test", +// CHECK: "EnumType": "uint", +// CHECK: "Values": [ +// CHECK: { +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "Test_A" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "Test_B" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 2, +// CHECK: "Symbol": { +// CHECK: "Name": "Test_C" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test2", +// CHECK: "NodeType": "Enum", +// CHECK: "Enum": { +// CHECK: "Name": "Test2", +// CHECK: "EnumType": "int", +// CHECK: "Values": [ +// CHECK: { +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 2, +// CHECK: "Symbol": { +// CHECK: "Name": "C" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test3", +// CHECK: "NodeType": "Enum", +// CHECK: "Enum": { +// CHECK: "Name": "Test3", +// CHECK: "EnumType": "int", +// CHECK: "Values": [ +// CHECK: { +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 2, +// CHECK: "Symbol": { +// CHECK: "Name": "C" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test4", +// CHECK: "NodeType": "Enum", +// CHECK: "Enum": { +// CHECK: "Name": "Test4", +// CHECK: "EnumType": "uint64_t", +// CHECK: "Values": [ +// CHECK: { +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 2, +// CHECK: "Symbol": { +// CHECK: "Name": "C" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test5", +// CHECK: "NodeType": "Enum", +// CHECK: "Enum": { +// CHECK: "Name": "Test5", +// CHECK: "EnumType": "int64_t", +// CHECK: "Values": [ +// CHECK: { +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 2, +// CHECK: "Symbol": { +// CHECK: "Name": "C" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test6", +// CHECK: "NodeType": "Enum", +// CHECK: "Enum": { +// CHECK: "Name": "Test6", +// CHECK: "EnumType": "uint", +// CHECK: "Values": [ +// CHECK: { +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 2, +// CHECK: "Symbol": { +// CHECK: "Name": "C" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test7", +// CHECK: "NodeType": "Enum", +// CHECK: "Enum": { +// CHECK: "Name": "Test7", +// CHECK: "EnumType": "int16_t", +// CHECK: "Values": [ +// CHECK: { +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 2, +// CHECK: "Symbol": { +// CHECK: "Name": "C" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test8", +// CHECK: "NodeType": "Enum", +// CHECK: "Enum": { +// CHECK: "Name": "Test8", +// CHECK: "EnumType": "uint16_t", +// CHECK: "Values": [ +// CHECK: { +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 2, +// CHECK: "Symbol": { +// CHECK: "Name": "C" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test", +// CHECK: "UnderlyingName": "uint" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test2", +// CHECK: "UnderlyingName": "int" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test3", +// CHECK: "UnderlyingName": "int" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "d", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test4", +// CHECK: "UnderlyingName": "uint64_t" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "e", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test5", +// CHECK: "UnderlyingName": "int64_t" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test6", +// CHECK: "UnderlyingName": "uint" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "g", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test7", +// CHECK: "UnderlyingName": "int16_t" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "h", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test8", +// CHECK: "UnderlyingName": "uint16_t" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "A", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test", +// CHECK: "UnderlyingName": "uint" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test2", +// CHECK: "UnderlyingName": "int" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test3", +// CHECK: "UnderlyingName": "int" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "d", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test4", +// CHECK: "UnderlyingName": "uint64_t" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "e", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test5", +// CHECK: "UnderlyingName": "int64_t" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test6", +// CHECK: "UnderlyingName": "uint" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "g", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test7", +// CHECK: "UnderlyingName": "int16_t" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "h", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test8", +// CHECK: "UnderlyingName": "uint16_t" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "sbuf", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "StructuredBuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "A", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "Test", +// CHECK: "UnderlyingName": "uint" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "TypeName": "Test2", +// CHECK: "UnderlyingName": "int" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "TypeName": "Test3", +// CHECK: "UnderlyingName": "int" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "d", +// CHECK: "TypeName": "Test4", +// CHECK: "UnderlyingName": "uint64_t" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "e", +// CHECK: "TypeName": "Test5", +// CHECK: "UnderlyingName": "int64_t" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f", +// CHECK: "TypeName": "Test6", +// CHECK: "UnderlyingName": "uint" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "g", +// CHECK: "TypeName": "Test7", +// CHECK: "UnderlyingName": "int16_t" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "h", +// CHECK: "TypeName": "Test8", +// CHECK: "UnderlyingName": "uint16_t" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "test", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "a": { +// CHECK: "TypeName": "Test", +// CHECK: "UnderlyingName": "uint" +// CHECK: }, +// CHECK: "b": { +// CHECK: "TypeName": "Test2", +// CHECK: "UnderlyingName": "int" +// CHECK: }, +// CHECK: "c": { +// CHECK: "TypeName": "Test3", +// CHECK: "UnderlyingName": "int" +// CHECK: }, +// CHECK: "d": { +// CHECK: "TypeName": "Test4", +// CHECK: "UnderlyingName": "uint64_t" +// CHECK: }, +// CHECK: "e": { +// CHECK: "TypeName": "Test5", +// CHECK: "UnderlyingName": "int64_t" +// CHECK: }, +// CHECK: "f": { +// CHECK: "TypeName": "Test6", +// CHECK: "UnderlyingName": "uint" +// CHECK: }, +// CHECK: "g": { +// CHECK: "TypeName": "Test7", +// CHECK: "UnderlyingName": "int16_t" +// CHECK: }, +// CHECK: "h": { +// CHECK: "TypeName": "Test8", +// CHECK: "UnderlyingName": "uint16_t" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/functions_semantics_interpolation.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/functions_semantics_interpolation.hlsl new file mode 100644 index 0000000000..e6b9ccc443 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/functions_semantics_interpolation.hlsl @@ -0,0 +1,125 @@ +// RUN: %dxreflector %s | FileCheck %s + +struct Test { + float3 pos : POSITION0; + nointerpolation uint test : FLAT0; +}; + +void testFunction(inout uint a, out uint b, in uint c) { + b = a | c; +} + +[[oxc::stage("vertex")]] +float4 mainVS(float2 uv : TEXCOORD0, nointerpolation uint test : KAAS0, Test t) : SV_POSITION { + return float4(uv * 2 - 1, 0, 1); +} + +[shader("pixel")] +float4 mainPS(float4 pos : SV_POSITION) : SV_TARGET { + return float4(pos.xy, 0, 1); +} + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "Test", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "pos", +// CHECK: "NodeType": "Variable", +// CHECK: "Semantic": "POSITION0", +// CHECK: "Type": { +// CHECK: "Name": "float3" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "test", +// CHECK: "NodeType": "Variable", +// CHECK: "Semantic": "FLAT0", +// CHECK: "Interpolation": "Constant", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "testFunction", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "a": { +// CHECK: "TypeName": "uint", +// CHECK: "Access": "inout" +// CHECK: }, +// CHECK: "b": { +// CHECK: "TypeName": "uint", +// CHECK: "Access": "out" +// CHECK: }, +// CHECK: "c": { +// CHECK: "TypeName": "uint", +// CHECK: "Access": "in" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "mainVS", +// CHECK: "NodeType": "Function", +// CHECK: "Semantic": "SV_POSITION", +// CHECK: "Annotations": [ +// CHECK: {{"\[\[oxc::stage\(\\\"vertex\\\"\)\]\]"}} +// CHECK: ], +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "uv": { +// CHECK: "TypeName": "float2", +// CHECK: "Semantic": "TEXCOORD0" +// CHECK: }, +// CHECK: "test": { +// CHECK: "TypeName": "uint", +// CHECK: "Semantic": "KAAS0", +// CHECK: "Interpolation": "Constant" +// CHECK: }, +// CHECK: "t": { +// CHECK: "TypeName": "Test" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "mainPS", +// CHECK: "NodeType": "Function", +// CHECK: "Semantic": "SV_TARGET", +// CHECK: "Annotations": [ +// CHECK: "[shader(\"pixel\")]" +// CHECK: ], +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "pos": { +// CHECK: "TypeName": "float4", +// CHECK: "Semantic": "SV_POSITION" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/inheritance.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/inheritance.hlsl new file mode 100644 index 0000000000..b327efd5bd --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/inheritance.hlsl @@ -0,0 +1,194 @@ +// RUN: %dxreflector %s | FileCheck %s + +struct A { + float4 color1 : COLOR1; +}; + +interface B { }; + +interface C { + float4 test(); +}; + +struct PSInput : A, B, C { + float4 color : COLOR; + float4 test() { return 2; } +}; + +StructuredBuffer buf; +PSInput var; + +float4 PSMain(PSInput input) : SV_TARGET { + return input.color1 * input.color * buf[0].color; +} + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "A", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "color1", +// CHECK: "NodeType": "Variable", +// CHECK: "Semantic": "COLOR1", +// CHECK: "Type": { +// CHECK: "Name": "float4" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "B", +// CHECK: "NodeType": "Interface" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "C", +// CHECK: "NodeType": "Interface", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "test", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "HasDefinition": false, +// CHECK: "Params": { +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "PSInput", +// CHECK: "NodeType": "Struct", +// CHECK: "Class": { +// CHECK: "BaseClass": { +// CHECK: "Name": "A" +// CHECK: }, +// CHECK: "Interfaces": [ +// CHECK: { +// CHECK: "Name": "B" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "color", +// CHECK: "NodeType": "Variable", +// CHECK: "Semantic": "COLOR", +// CHECK: "Type": { +// CHECK: "Name": "float4" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "test", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "buf", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "StructuredBuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "PSInput", +// CHECK: "BaseClass": { +// CHECK: "TypeName": "A", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "color1", +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: "Interfaces": [ +// CHECK: { +// CHECK: "Name": "B" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "color", +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "var", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "PSInput", +// CHECK: "BaseClass": { +// CHECK: "TypeName": "A", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "color1", +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: "Interfaces": [ +// CHECK: { +// CHECK: "Name": "B" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "color", +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "PSMain", +// CHECK: "NodeType": "Function", +// CHECK: "Semantic": "SV_TARGET", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "input": { +// CHECK: "TypeName": "PSInput" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/recursive_buffer.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/recursive_buffer.hlsl new file mode 100644 index 0000000000..565896d149 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/recursive_buffer.hlsl @@ -0,0 +1,268 @@ +// RUN: %dxreflector %s | FileCheck %s + +struct A { + float a; +}; + +struct B { + A a; + float b; +}; + +struct C { + B b; + float c; +}; + +struct D { + C c; + float d; +}; + +StructuredBuffer buf; +D var; + +void test(D d) { } + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "A", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "B", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "A", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "C", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "B", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "A", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "D", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "C", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "TypeName": "B", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "A", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "d", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "buf", +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterType": "StructuredBuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "$Element", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "D", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "TypeName": "C", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "TypeName": "B", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "A", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "d", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "var", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "D", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "TypeName": "C", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "TypeName": "B", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "A", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "d", +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "test", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "d": { +// CHECK: "TypeName": "D" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/stripped_variable_types.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/stripped_variable_types.hlsl new file mode 100644 index 0000000000..758808e990 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/stripped_variable_types.hlsl @@ -0,0 +1,306 @@ +// RUN: %dxreflector -reflect-disable-symbols %s | FileCheck %s + +struct T { + uint otherData[4]; +}; + +groupshared uint groupData[16]; +static const uint staticData[4] = { 0, 1, 2, 3 }; +uint dynamicData[4]; +StructuredBuffer other; + +struct Test { + static const uint staticData = 0; + static float adds(float a, float b) { return a + b; } + float add(float a, float b) { return a + b; } +}; + +namespace tst { + + static const uint staticData[4] = { 0, 1, 2, 3 }; + float add(float a, float b) { return a + b; } + + struct Test { + static const uint staticData = 0; + static float adds(float a, float b) { return a + b; } + float add(float a, float b) { return a + b; } + }; +} + +typedef float f32; + +f32 add(float a, float b) { return a + b; } + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeId": 1, +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeId": 2, +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "TypeId": 0, +// CHECK: "Name": "uint", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 3, +// CHECK: "NodeType": "GroupsharedVariable", +// CHECK: "Type": { +// CHECK: "TypeId": 2, +// CHECK: "Name": "uint", +// CHECK: "ArraySize": [ +// CHECK: 16 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 4, +// CHECK: "NodeType": "StaticVariable", +// CHECK: "Type": { +// CHECK: "TypeId": 0, +// CHECK: "Name": "uint", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 5, +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "TypeId": 0, +// CHECK: "Name": "uint", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 6, +// CHECK: "NodeType": "Register", +// CHECK: "Register": { +// CHECK: "RegisterId": 0, +// CHECK: "NodeId": 6, +// CHECK: "RegisterType": "StructuredBuffer" +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeId": 7, +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "TypeId": 3, +// CHECK: "Members": [ +// CHECK: { +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "uint", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 8, +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeId": 9, +// CHECK: "NodeType": "StaticVariable", +// CHECK: "Type": { +// CHECK: "TypeId": 5, +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 10, +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "FunctionId": 0, +// CHECK: "NodeId": 10, +// CHECK: "Params": { +// CHECK: "0": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: }, +// CHECK: "1": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 14, +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "FunctionId": 1, +// CHECK: "NodeId": 14, +// CHECK: "Params": { +// CHECK: "0": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: }, +// CHECK: "1": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 18, +// CHECK: "NodeType": "Namespace", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeId": 19, +// CHECK: "NodeType": "StaticVariable", +// CHECK: "Type": { +// CHECK: "TypeId": 0, +// CHECK: "Name": "uint", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 20, +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "FunctionId": 2, +// CHECK: "NodeId": 20, +// CHECK: "Params": { +// CHECK: "0": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: }, +// CHECK: "1": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 24, +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeId": 25, +// CHECK: "NodeType": "StaticVariable", +// CHECK: "Type": { +// CHECK: "TypeId": 5, +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 26, +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "FunctionId": 3, +// CHECK: "NodeId": 26, +// CHECK: "Params": { +// CHECK: "0": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: }, +// CHECK: "1": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 30, +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "FunctionId": 4, +// CHECK: "NodeId": 30, +// CHECK: "Params": { +// CHECK: "0": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: }, +// CHECK: "1": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 34, +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "TypeId": 6, +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 35, +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "FunctionId": 5, +// CHECK: "NodeId": 35, +// CHECK: "Params": { +// CHECK: "0": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: }, +// CHECK: "1": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/variable_types.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/variable_types.hlsl new file mode 100644 index 0000000000..0b972fe291 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/variable_types.hlsl @@ -0,0 +1,92 @@ +// RUN: %dxreflector %s | FileCheck %s + +groupshared uint groupData[16]; +static const uint staticData[4] = { 0, 1, 2, 3 }; + +struct Test { + static const uint staticData = 0; +}; + +namespace tst { + + static const uint staticData[4] = { 0, 1, 2, 3 }; + + struct Test { + static const uint staticData = 0; + }; +} + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "groupData", +// CHECK: "NodeType": "GroupsharedVariable", +// CHECK: "Type": { +// CHECK: "Name": "uint", +// CHECK: "ArraySize": [ +// CHECK: 16 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "staticData", +// CHECK: "NodeType": "StaticVariable", +// CHECK: "Type": { +// CHECK: "Name": "uint", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "staticData", +// CHECK: "NodeType": "StaticVariable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "tst", +// CHECK: "NodeType": "Namespace", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "staticData", +// CHECK: "NodeType": "StaticVariable", +// CHECK: "Type": { +// CHECK: "Name": "uint", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "staticData", +// CHECK: "NodeType": "StaticVariable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 82b7e23c9f..adc910fd87 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -357,7 +357,7 @@ static std::string BufferTypeToString(D3D_CBUFFER_TYPE Type) { static std::string GetBuiltinTypeName(const ReflectionData &Refl, const ReflectionVariableType &Type) { - std::string type = ""; + std::string type = ""; if (Type.GetClass() != D3D_SVC_STRUCT && Type.GetClass() != D3D_SVC_INTERFACE_CLASS) { From d82d516dd45c02f1993dc79e8cf01f92124de2f9 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 12 Nov 2025 21:40:42 +0100 Subject: [PATCH 114/126] Added walking of templates to collect underlying types and added a test to show what is supported with templates/using and what isn't --- .../dxreflector/templates_and_using.hlsl | 414 ++++++++++++++++++ .../dxcreflection/dxcreflection_from_ast.cpp | 11 + 2 files changed, 425 insertions(+) create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/templates_and_using.hlsl diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/templates_and_using.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/templates_and_using.hlsl new file mode 100644 index 0000000000..25bfbba4ec --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/templates_and_using.hlsl @@ -0,0 +1,414 @@ +// RUN: %dxreflector %s | FileCheck %s + +//TODO: Expose these to the AST, now they get ignored +// unless they get instantiated in a variable, struct member or function param +// This means you have to be a bit careful when walking the tree +// since some things might be missing. +template +struct ForSomeReasonAVector { + + T data[N]; + + template + void add(ForSomeReasonAVector v) { + for(uint i = 0; i < M && i < N; ++i) + data[i] += v.data[i]; + } +}; + +template +ForSomeReasonAVector pow2(ForSomeReasonAVector v) { + for(uint i = 0; i < M; ++i) + v.data[i] *= v.data[i]; +} + +template +using Test = float[N]; + +//Supported types using a using or template type + +typedef ForSomeReasonAVector F32x4; +typedef ForSomeReasonAVector U32x2; +typedef Test<4> Test4; +typedef Test<2> Test2; + +struct Struct { + ForSomeReasonAVector a; + ForSomeReasonAVector b; + Test<4> c; + Test<2> d; + F32x4 e; + U32x2 f; + Test4 g; + Test2 h; +}; + +ForSomeReasonAVector a; +ForSomeReasonAVector b; +Test<4> c; +Test<2> d; +F32x4 e; +U32x2 f; +Test4 g; +Test2 h; + +void func( + ForSomeReasonAVector a, + ForSomeReasonAVector b, + Test<4> c, + Test<2> d, + F32x4 e, + U32x2 f, + Test4 g, + Test2 h +) { } + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "F32x4", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "ForSomeReasonAVector", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "data", +// CHECK: "TypeName": "float", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "U32x2", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "ForSomeReasonAVector", +// CHECK: "UnderlyingName": "ForSomeReasonAVector", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "data", +// CHECK: "TypeName": "unsigned int", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test4", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "Test<4>", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test2", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "Test<2>", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Struct", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "ForSomeReasonAVector", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "data", +// CHECK: "TypeName": "float", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "ForSomeReasonAVector", +// CHECK: "UnderlyingName": "ForSomeReasonAVector", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "data", +// CHECK: "TypeName": "unsigned int", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test<4>", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "d", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test<2>", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "e", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "F32x4", +// CHECK: "UnderlyingName": "ForSomeReasonAVector", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "data", +// CHECK: "TypeName": "float", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "U32x2", +// CHECK: "UnderlyingName": "ForSomeReasonAVector", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "data", +// CHECK: "TypeName": "unsigned int", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "g", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test4", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "h", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test2", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "ForSomeReasonAVector", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "data", +// CHECK: "TypeName": "float", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "ForSomeReasonAVector", +// CHECK: "UnderlyingName": "ForSomeReasonAVector", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "data", +// CHECK: "TypeName": "unsigned int", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test<4>", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "d", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test<2>", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "e", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "F32x4", +// CHECK: "UnderlyingName": "ForSomeReasonAVector", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "data", +// CHECK: "TypeName": "float", +// CHECK: "ArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "U32x2", +// CHECK: "UnderlyingName": "ForSomeReasonAVector", +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "data", +// CHECK: "TypeName": "unsigned int", +// CHECK: "ArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "g", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test4", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "h", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "Test2", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "func", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "a": { +// CHECK: "TypeName": "ForSomeReasonAVector" +// CHECK: }, +// CHECK: "b": { +// CHECK: "TypeName": "ForSomeReasonAVector", +// CHECK: "UnderlyingName": "ForSomeReasonAVector" +// CHECK: }, +// CHECK: "c": { +// CHECK: "TypeName": "Test<4>", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: }, +// CHECK: "d": { +// CHECK: "TypeName": "Test<2>", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: }, +// CHECK: "e": { +// CHECK: "TypeName": "F32x4", +// CHECK: "UnderlyingName": "ForSomeReasonAVector" +// CHECK: }, +// CHECK: "f": { +// CHECK: "TypeName": "U32x2", +// CHECK: "UnderlyingName": "ForSomeReasonAVector" +// CHECK: }, +// CHECK: "g": { +// CHECK: "TypeName": "Test4", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 4 +// CHECK: ] +// CHECK: }, +// CHECK: "h": { +// CHECK: "TypeName": "Test2", +// CHECK: "UnderlyingName": "float", +// CHECK: "UnderlyingArraySize": [ +// CHECK: 2 +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 0a22764d5a..8b88f76f39 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -609,6 +609,17 @@ CollectUnderlyingArraySizes(QualType &T, std::vector &Out, return err; } + if (const TemplateSpecializationType *ts = + dyn_cast(T)) { + QualType desugared = ts->desugar().getNonReferenceType(); + if (desugared != T) { + T = desugared; + if (ReflectionError err = + CollectUnderlyingArraySizes(T, Out, FlatSize)) + return err; + } + } + Out.insert(Out.end(), local.begin(), local.end()); return ReflectionErrorSuccess; } From 7521677c1e08e29090073aa5ba21af0e70c65392 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 12 Nov 2025 22:11:16 +0100 Subject: [PATCH 115/126] Added unit test for showing symbols (file loc + line, column, etc.). Removed redundant json creation in dxcreflector.cpp. Symbols printed as a child now only show the name in the child and the symbol as a separate object. --- .../dxreflector/sources_test.hlsl | 200 ++++++++++++++++++ .../tools/dxcreflection/dxcreflector.cpp | 10 +- .../DxcReflectionJson.cpp | 6 +- .../unittests/HLSLTestLib/FileCheckerTest.cpp | 3 +- 4 files changed, 206 insertions(+), 13 deletions(-) create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/sources_test.hlsl diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/sources_test.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/sources_test.hlsl new file mode 100644 index 0000000000..d4e1861d54 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/sources_test.hlsl @@ -0,0 +1,200 @@ +// RUN: %dxreflector -reflect-show-file-info %s | FileCheck %s + +typedef float B; +float a; + +enum class Test { + A, + B +}; + +struct A { + float a; + void test() {} +}; + +void test(A a, float b) {} + +namespace tst { + float a; +} + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "B", +// CHECK: "NodeType": "Typedef", +// CHECK: "Symbol": { +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 3, +// CHECK: "ColumnStart": 1, +// CHECK: "ColumnEnd": 16 +// CHECK: }, +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Symbol": { +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 4, +// CHECK: "ColumnStart": 1, +// CHECK: "ColumnEnd": 8 +// CHECK: }, +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test", +// CHECK: "NodeType": "Enum", +// CHECK: "Symbol": { +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 6, +// CHECK: "LineCount": 4, +// CHECK: "ColumnStart": 1, +// CHECK: "ColumnEnd": 2 +// CHECK: }, +// CHECK: "Enum": { +// CHECK: "Name": "Test", +// CHECK: "EnumType": "int", +// CHECK: "Values": [ +// CHECK: { +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A", +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 7, +// CHECK: "ColumnStart": 2, +// CHECK: "ColumnEnd": 3 +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B", +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 8, +// CHECK: "ColumnStart": 2, +// CHECK: "ColumnEnd": 3 +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "A", +// CHECK: "NodeType": "Struct", +// CHECK: "Symbol": { +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 11, +// CHECK: "LineCount": 4, +// CHECK: "ColumnStart": 1, +// CHECK: "ColumnEnd": 2 +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Symbol": { +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 12, +// CHECK: "ColumnStart": 2, +// CHECK: "ColumnEnd": 9 +// CHECK: }, +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "test", +// CHECK: "NodeType": "Function", +// CHECK: "Symbol": { +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 13, +// CHECK: "ColumnStart": 2, +// CHECK: "ColumnEnd": 16 +// CHECK: }, +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "test", +// CHECK: "NodeType": "Function", +// CHECK: "Symbol": { +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 16, +// CHECK: "ColumnStart": 1, +// CHECK: "ColumnEnd": 27 +// CHECK: }, +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "a": { +// CHECK: "Symbol": { +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 16, +// CHECK: "ColumnStart": 11, +// CHECK: "ColumnEnd": 14 +// CHECK: }, +// CHECK: "TypeName": "A" +// CHECK: }, +// CHECK: "b": { +// CHECK: "Symbol": { +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 16, +// CHECK: "ColumnStart": 16, +// CHECK: "ColumnEnd": 23 +// CHECK: }, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "tst", +// CHECK: "NodeType": "Namespace", +// CHECK: "Symbol": { +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 18, +// CHECK: "LineCount": 3, +// CHECK: "ColumnStart": 1, +// CHECK: "ColumnEnd": 2 +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Symbol": { +// CHECK: "Source": "{{.*}}sources_test.hlsl", +// CHECK: "LineId": 19, +// CHECK: "ColumnStart": 2, +// CHECK: "ColumnEnd": 9 +// CHECK: }, +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index f347a59d15..a6dff9659b 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -1759,18 +1759,10 @@ class DxcReflector : public IHLSLReflector, public IDxcLangExtensions3 { errors, rewrite, msfPtr, reflection); std::vector Bytes; - std::string json; - - if (SUCCEEDED(status)) { + if (SUCCEEDED(status)) reflection.Dump(Bytes); - bool hideFileInfo = !opts.ReflOpt.ShowFileInfo; - bool humanFriendly = !opts.ReflOpt.ShowRawData; - - json = reflection.ToJson(hideFileInfo, humanFriendly); - } - return DxcResult::Create( status, DXC_OUT_OBJECT, {DxcOutputObject::ObjectOutput(Bytes.data(), Bytes.size()), diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index adc910fd87..336b13560b 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -480,7 +480,7 @@ struct ReflectionPrintSettings { static void PrintSymbol(JsonWriter &Json, const ReflectionData &Reflection, const ReflectionNodeSymbol &Sym, const ReflectionPrintSettings &Settings, - bool MuteName) { + bool MuteName, bool ShowOnlyName = false) { if (Sym.GetNameId() && !MuteName) { @@ -490,7 +490,7 @@ static void PrintSymbol(JsonWriter &Json, const ReflectionData &Reflection, Json.UIntField("NameId", Sym.GetNameId()); } - if (Settings.HideFileInfo) + if (Settings.HideFileInfo || ShowOnlyName) return; if (Sym.HasFileSource()) { @@ -1105,7 +1105,7 @@ void PrintChildren(const ReflectionData &Data, JsonWriter &Json, // Put Name(Id) into current scope to hide "Symbol" everywhere. if (Data.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) - PrintSymbol(Json, Data, Data.NodeSymbols[i], Settings, false); + PrintSymbol(Json, Data, Data.NodeSymbols[i], Settings, false, true); i += PrintNodeRecursive(Data, i, Json, Settings); } diff --git a/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp b/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp index df2e016a9c..c65c070b81 100644 --- a/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp +++ b/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp @@ -609,7 +609,8 @@ FileRunCommandPart::RunDxReflector(dxc::DllLoader &DllSupport, UNREFERENCED_PARAMETER(Prior); hlsl::options::MainArgs args; hlsl::options::DxcOpts opts; - FileRunCommandResult readOptsResult = ReadOptsForDxc(args, opts); + FileRunCommandResult readOptsResult = + ReadOptsForDxc(args, opts, hlsl::options::ReflectOption); if (readOptsResult.ExitCode) return readOptsResult; From 16abf1f553137c42f709ed622c6d34d5a1d4e2d0 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 12 Nov 2025 22:19:48 +0100 Subject: [PATCH 116/126] Added a raw data test --- .../dxreflector/raw_data_test.hlsl | 469 ++++++++++++++++++ 1 file changed, 469 insertions(+) create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl new file mode 100644 index 0000000000..27bd3c0313 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl @@ -0,0 +1,469 @@ +// RUN: %dxreflector -reflect-show-raw-data %s | FileCheck %s + +typedef float B; +float a[2][3]; + +enum class Test { + A, + B +}; + +interface C {}; + +struct A : C { + float a; + void test() {} +}; + +ConstantBuffer b; + +[[oxc::fancy]] +void test(A a, float b) { + if(b) {} + else {} +} + +namespace tst { + float a; +} + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Strings": [ +// CHECK: "", +// CHECK: "float", +// CHECK: "{{.*}}raw_data_test.hlsl", +// CHECK: "B", +// CHECK: "a", +// CHECK: "Test", +// CHECK: "A", +// CHECK: "C", +// CHECK: "test", +// CHECK: "b", +// CHECK: "tst" +// CHECK: ], +// CHECK: "StringsNonDebug": [ +// CHECK: "oxc::fancy" +// CHECK: ], +// CHECK: "Sources": [ +// CHECK: "{{.*}}raw_data_test.hlsl" +// CHECK: ], +// CHECK: "SourcesAsId": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "Nodes": [ +// CHECK: { +// CHECK: "NodeId": 0, +// CHECK: "NodeType": "Namespace", +// CHECK: "NodeTypeId": 4, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": -1, +// CHECK: "ChildCount": 17, +// CHECK: "ChildStart": 1 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 1, +// CHECK: "NodeType": "Typedef", +// CHECK: "NodeTypeId": 6, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 0 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 2, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 0 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 3, +// CHECK: "NodeType": "Enum", +// CHECK: "NodeTypeId": 2, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 0, +// CHECK: "ChildCount": 2, +// CHECK: "ChildStart": 4 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 4, +// CHECK: "NodeType": "EnumValue", +// CHECK: "NodeTypeId": 3, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 3 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 5, +// CHECK: "NodeType": "EnumValue", +// CHECK: "NodeTypeId": 3, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 3 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 6, +// CHECK: "NodeType": "Interface", +// CHECK: "NodeTypeId": 10, +// CHECK: "LocalId": 2, +// CHECK: "ParentId": 0 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 7, +// CHECK: "NodeType": "Struct", +// CHECK: "NodeTypeId": 7, +// CHECK: "LocalId": 3, +// CHECK: "ParentId": 0, +// CHECK: "ChildCount": 2, +// CHECK: "ChildStart": 8 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 8, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 7 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 9, +// CHECK: "NodeType": "Function", +// CHECK: "NodeTypeId": 1, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 7 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 10, +// CHECK: "NodeType": "Register", +// CHECK: "NodeTypeId": 0, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 0, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 11 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 11, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 4, +// CHECK: "ParentId": 10 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 12, +// CHECK: "NodeType": "Function", +// CHECK: "NodeTypeId": 1, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 0, +// CHECK: "ChildCount": 3, +// CHECK: "ChildStart": 13, +// CHECK: "AnnotationStart": 0, +// CHECK: "AnnotationCount": 1, +// CHECK: "Annotations": [ +// CHECK: "{{\[\[oxc::fancy\]\]}}" +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 13, +// CHECK: "NodeType": "Parameter", +// CHECK: "NodeTypeId": 11, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 12 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 14, +// CHECK: "NodeType": "Parameter", +// CHECK: "NodeTypeId": 11, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 12 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 15, +// CHECK: "NodeType": "If", +// CHECK: "NodeTypeId": 12, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 12 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 16, +// CHECK: "NodeType": "Namespace", +// CHECK: "NodeTypeId": 4, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 0, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 17 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 17, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 16 +// CHECK: } +// CHECK: ], +// CHECK: "Registers": [ +// CHECK: { +// CHECK: "RegisterId": 0, +// CHECK: "NodeId": 10, +// CHECK: "Name": "b", +// CHECK: "RegisterType": "cbuffer", +// CHECK: "BufferId": 0 +// CHECK: } +// CHECK: ], +// CHECK: "Functions": [ +// CHECK: { +// CHECK: "FunctionId": 0, +// CHECK: "NodeId": 9, +// CHECK: "Name": "test", +// CHECK: "HasDefinition": true, +// CHECK: "Params": { +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "FunctionId": 1, +// CHECK: "NodeId": 12, +// CHECK: "Name": "test", +// CHECK: "HasDefinition": true, +// CHECK: "Params": { +// CHECK: "a": { +// CHECK: "TypeId": 5, +// CHECK: "TypeName": "A" +// CHECK: }, +// CHECK: "b": { +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Parameters": [ +// CHECK: { +// CHECK: "ParamName": "a", +// CHECK: "TypeId": 5, +// CHECK: "TypeName": "A" +// CHECK: }, +// CHECK: { +// CHECK: "ParamName": "b", +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ], +// CHECK: "Enums": [ +// CHECK: { +// CHECK: "EnumId": 0, +// CHECK: "NodeId": 3, +// CHECK: "Name": "Test", +// CHECK: "EnumType": "int", +// CHECK: "Values": [ +// CHECK: { +// CHECK: "ValueId": 0, +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A", +// CHECK: "NameId": 6 +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "ValueId": 1, +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B", +// CHECK: "NameId": 3 +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ], +// CHECK: "EnumValues": [ +// CHECK: { +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A", +// CHECK: "NameId": 6 +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B", +// CHECK: "NameId": 3 +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Annotations": [ +// CHECK: { +// CHECK: "StringId": 0, +// CHECK: "Contents": "oxc::fancy", +// CHECK: "Type": "User" +// CHECK: } +// CHECK: ], +// CHECK: "Arrays": [ +// CHECK: { +// CHECK: "ArrayElem": 2, +// CHECK: "ArrayStart": 0, +// CHECK: "ArraySizes": [ +// CHECK: 2, +// CHECK: 3 +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "ArrayElem": 2, +// CHECK: "ArrayStart": 2, +// CHECK: "ArraySizes": [ +// CHECK: 2, +// CHECK: 3 +// CHECK: ] +// CHECK: } +// CHECK: ], +// CHECK: "ArraySizes": [ +// CHECK: 2, +// CHECK: 3, +// CHECK: 2, +// CHECK: 3 +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ], +// CHECK: "TypeList": [ +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Types": [ +// CHECK: { +// CHECK: "TypeId": 0, +// CHECK: "Name": "float" +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 1, +// CHECK: "Name": "float", +// CHECK: "ArraySize": [ +// CHECK: 2, +// CHECK: 3 +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 3, +// CHECK: "Name": "A", +// CHECK: "Interfaces": [ +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 4, +// CHECK: "Name": "A", +// CHECK: "Interfaces": [ +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 5, +// CHECK: "Name": "A", +// CHECK: "Interfaces": [ +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ], +// CHECK: "Buffers": [ +// CHECK: { +// CHECK: "BufferId": 0, +// CHECK: "NodeId": 10, +// CHECK: "Name": "b", +// CHECK: "Type": "cbuffer", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeId": 11, +// CHECK: "ChildId": 0, +// CHECK: "Name": "b", +// CHECK: "TypeId": 4, +// CHECK: "TypeName": "A", +// CHECK: "Interfaces": [ +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ], +// CHECK: "Statements": [ +// CHECK: { +// CHECK: "Type": "If", +// CHECK: "NodeId": 15, +// CHECK: "HasConditionVar": false, +// CHECK: "HasElse": true +// CHECK: } +// CHECK: ] +// CHECK: } From 5c69ad20353782a369b83dc188aae18e6bac52dd Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Wed, 12 Nov 2025 22:47:24 +0100 Subject: [PATCH 117/126] Added name to Condition variable in for/if/etc. Added unit tests for Stmtsg --- .../HLSLFileCheck/dxreflector/stmt_test.hlsl | 378 ++++++++++++++++++ .../DxcReflectionJson.cpp | 16 +- 2 files changed, 388 insertions(+), 6 deletions(-) create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl new file mode 100644 index 0000000000..56e5bb4c36 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl @@ -0,0 +1,378 @@ +// RUN: %dxreflector %s | FileCheck %s + +void test(uint b) { + + if(uint d = b ^ 0x13) { + float c; + } + + else { + float c; + } + + while(true) { + float c; + break; + } + + while(uint d = b ^ 0x13) { + float c; + break; + } + + do { + float c; + break; + } while(b ^ 0x13); + + { + float c; + } + + for(uint i = 0; i < 5; ++i) { + float c; + } + + [unroll] + for(uint i = 0; i < 2; ++i) { + float c; + } + + for(uint i = 0, j = 5; bool k = i < 2; ++i, ++j) { + float c; + } + + //TODO: turn into a smaller chain of ifs + + if(b == 0) { + float c; + } + else if(b == 1) { + float c; + } + else if(b == 2) { + float c; + } + else if(b == 3) { + float c; + } + else { + float c; + } + + //TODO: Cases not working yet + + switch(uint d = b ^ 0x13) { + case 0: + float c; + break; + } + + switch(b) { + case 0: { + float c; + break; + } + case 1: { + float c; + break; + } + case 2: { + float c; + break; + } + case 3: { + float c; + break; + } + } +} + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "test", +// CHECK: "NodeType": "Function", +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "b": { +// CHECK: "TypeName": "uint" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "If", +// CHECK: "If": { +// CHECK: "Condition": { +// CHECK: "Name": "d", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: }, +// CHECK: "Body": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Else": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "While", +// CHECK: "While": { +// CHECK: "Body": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "While", +// CHECK: "While": { +// CHECK: "Condition": { +// CHECK: "Name": "d", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: }, +// CHECK: "Body": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Do", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Scope", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "For", +// CHECK: "For": { +// CHECK: "Init": [ +// CHECK: { +// CHECK: "Name": "i", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Body": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "For", +// CHECK: "For": { +// CHECK: "Init": [ +// CHECK: { +// CHECK: "Name": "i", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Body": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "For", +// CHECK: "For": { +// CHECK: "Condition": { +// CHECK: "Name": "k", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "bool" +// CHECK: } +// CHECK: }, +// CHECK: "Init": [ +// CHECK: { +// CHECK: "Name": "i", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "j", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Body": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "If", +// CHECK: "If": { +// CHECK: "Body": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Else": [ +// CHECK: { +// CHECK: "NodeType": "If", +// CHECK: "If": { +// CHECK: "Body": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Else": [ +// CHECK: { +// CHECK: "NodeType": "If", +// CHECK: "If": { +// CHECK: "Body": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Else": [ +// CHECK: { +// CHECK: "NodeType": "If", +// CHECK: "If": { +// CHECK: "Body": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Else": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Switch", +// CHECK: "Switch": { +// CHECK: "Condition": { +// CHECK: "Name": "d", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Switch", +// CHECK: "Switch": { +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 336b13560b..58ca9e4cbc 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -1245,18 +1245,22 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, if (stmtType) { Json.Object(stmtType, [&node, &Reflection, &Json, &Settings, NodeId, - &childrenToSkip, nodeType]() { + &childrenToSkip, nodeType, hasSymbols]() { const ReflectionScopeStmt &stmt = Reflection.Statements[node.GetLocalId()]; uint32_t start = NodeId + 1; if (stmt.HasConditionVar()) - Json.Object( - "Condition", [NodeId, &Reflection, &Json, &start, &Settings]() { - start += PrintNodeRecursive(Reflection, start, Json, Settings); - ++start; - }); + Json.Object("Condition", [NodeId, &Reflection, &Json, &start, &Settings, + hasSymbols]() { + if (hasSymbols) + PrintSymbol(Json, Reflection, Reflection.NodeSymbols[start], + Settings, false, true); + + start += PrintNodeRecursive(Reflection, start, Json, Settings); + ++start; + }); uint32_t end = start + stmt.GetNodeCount(); From e9688d8902ab6a47948de62444247f9a8253af3d Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Thu, 13 Nov 2025 02:22:51 +0100 Subject: [PATCH 118/126] Added ReflectionIfSwitchStmt and ReflectionBranchStmt. This allows case/default and in the future if/else if/else to be done through a single parent node. Added some unit tests for switch. Enum (data) type is now also used for storing case info. Changed the statement walking from a switch case to an explicit walk to properly go through the cases and default. Added validation for switch/case/default. --- .../DxcReflection/DxcReflectionContainer.h | 109 +++- include/dxc/dxcreflect.h | 16 +- .../dxreflector/raw_data_test.hlsl | 503 +++++++++++++++++- .../HLSLFileCheck/dxreflector/stmt_test.hlsl | 197 ++++++- .../dxcreflection/dxcreflection_from_ast.cpp | 186 ++++++- .../DxcReflectionContainer.cpp | 259 +++++++-- .../DxcReflectionJson.cpp | 141 ++++- 7 files changed, 1293 insertions(+), 118 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflectionContainer.h b/include/dxc/DxcReflection/DxcReflectionContainer.h index 48ae8bf874..3380d57a65 100644 --- a/include/dxc/DxcReflection/DxcReflectionContainer.h +++ b/include/dxc/DxcReflection/DxcReflectionContainer.h @@ -384,8 +384,7 @@ struct ReflectionFunctionParameter { // Mirrors D3D12_PARAMETER_DESC without } }; -// A statement is a for, while, if, switch. Basically every Stmt except do or -// scope. It can contain the following child nodes: +// A statement is a for or a while statement. // - if HasConditionVar(): a variable in the condition // - NodeCount children (If: children ex. else body, For: init children) // - Rest of the body (If: else body, otherwise: normal body) @@ -438,6 +437,106 @@ class ReflectionScopeStmt { } }; +// An if/switch statement holds the following. +// - if HasConditionVar(): a variable in the switch condition (unused for if) +// - BranchCount (inc. default/else, implicit->childCount) +// Each branch then has a: +// - counter (or value for switch/case (non default)) +// - if HasConditionVar(): a variable in the if +// - nodeCount (implicit) for the contents. +class ReflectionIfSwitchStmt { + + uint32_t NodeId; + + union { + uint32_t ConditionVarElseOrDefault; + struct { + uint16_t Padding; + bool ConditionVar; + bool ElseOrDefault; + }; + }; + + ReflectionIfSwitchStmt(uint32_t NodeId, bool ConditionVar, bool ElseOrDefault) + : NodeId(NodeId), Padding(0), ConditionVar(ConditionVar), + ElseOrDefault(ElseOrDefault) {} + +public: + ReflectionIfSwitchStmt() = default; + + [[nodiscard]] static ReflectionError + Initialize(ReflectionIfSwitchStmt &IfSwitchStmt, uint32_t NodeId, + bool HasConditionVar, bool HasElseOrDefault) { + + IfSwitchStmt = + ReflectionIfSwitchStmt(NodeId, HasConditionVar, HasElseOrDefault); + return ReflectionErrorSuccess; + } + + uint32_t GetNodeId() const { return NodeId; } + + bool HasConditionVar() const { return ConditionVar; } + bool HasElseOrDefault() const { return ElseOrDefault; } + + bool operator==(const ReflectionIfSwitchStmt &Other) const { + return NodeId == Other.NodeId && + ConditionVarElseOrDefault == Other.ConditionVarElseOrDefault; + } +}; + +class ReflectionBranchStmt { + + union { + uint64_t NodeIdConditionVarType; + struct { + uint32_t NodeId; + bool ConditionVar; + bool ComplexCase; + uint8_t ValueType; // D3D12_HLSL_ENUM_TYPE + uint8_t Padding; + }; + }; + + uint64_t Value; + + ReflectionBranchStmt(uint32_t NodeId, bool ConditionVar, bool ComplexCase, + D3D12_HLSL_ENUM_TYPE ValueType, uint64_t Value) + : NodeId(NodeId), ConditionVar(ConditionVar), ComplexCase(ComplexCase), + ValueType(ValueType), Padding(0), Value(Value) {} + +public: + ReflectionBranchStmt() = default; + + [[nodiscard]] static ReflectionError + Initialize(ReflectionBranchStmt &BranchStmt, uint32_t NodeId, + bool ConditionVar, bool ComplexCase, + D3D12_HLSL_ENUM_TYPE ValueType, uint64_t Value) { + + if (ValueType < D3D12_HLSL_ENUM_TYPE_UINT || + ValueType > D3D12_HLSL_ENUM_TYPE_INT16_T) + return HLSL_REFL_ERR("ValueType out of bounds"); + + BranchStmt = ReflectionBranchStmt(NodeId, ConditionVar, ComplexCase, + ValueType, Value); + return ReflectionErrorSuccess; + } + + // Only (16-bit, 32-bit or 64-bit)(signed, unsigned) + D3D12_HLSL_ENUM_TYPE GetValueType() const { + return D3D12_HLSL_ENUM_TYPE(ValueType); + } + + uint32_t GetNodeId() const { return NodeId; } + uint64_t GetValue() const { return Value; } // Manually cast this + bool HasConditionVar() const { return ConditionVar; } + bool IsComplexCase() const { return ComplexCase; } + + bool operator==(const ReflectionBranchStmt &Other) const { + return NodeIdConditionVarType == Other.NodeIdConditionVarType && + Value == Other.Value; + } +}; + class ReflectionFunction { uint32_t NodeId; @@ -843,6 +942,8 @@ struct ReflectionData { std::vector Buffers; std::vector Statements; + std::vector IfSwitchStatements; + std::vector BranchStatements; // Can be stripped if !(D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO) @@ -889,7 +990,9 @@ struct ReflectionData { ArraySizes == Other.ArraySizes && MemberTypeIds == Other.MemberTypeIds && TypeList == Other.TypeList && Types == Other.Types && Buffers == Other.Buffers && - Parameters == Other.Parameters && Statements == Other.Statements; + Parameters == Other.Parameters && Statements == Other.Statements && + IfSwitchStatements == Other.IfSwitchStatements && + BranchStatements == Other.BranchStatements; } bool operator==(const ReflectionData &Other) const { diff --git a/include/dxc/dxcreflect.h b/include/dxc/dxcreflect.h index 459b160744..29cbace06c 100644 --- a/include/dxc/dxcreflect.h +++ b/include/dxc/dxcreflect.h @@ -146,10 +146,10 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_INTERFACE, D3D12_HLSL_NODE_TYPE_PARAMETER, - // Control flow (Stmts), for full inspection of what variables exist where and + // Control flow (Stmts or SwitchIfStmt), for full inspection of what variables exist where and // scopes - D3D12_HLSL_NODE_TYPE_IF, + D3D12_HLSL_NODE_TYPE_IF, //TODO: Rename to if root D3D12_HLSL_NODE_TYPE_SCOPE, D3D12_HLSL_NODE_TYPE_DO, D3D12_HLSL_NODE_TYPE_SWITCH, @@ -158,6 +158,15 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE, + // All branches (BranchStmt) + + D3D12_HLSL_NODE_TYPE_CASE, + D3D12_HLSL_NODE_TYPE_DEFAULT, + + //D3D12_HLSL_NODE_TYPE_IF_FIRST, + //D3D12_HLSL_NODE_TYPE_ELSE_IF, + //D3D12_HLSL_NODE_TYPE_ELSE, + // TODO: D3D12_HLSL_NODE_TYPE_USING, D3D12_HLSL_NODE_TYPE_RESERVED = @@ -166,7 +175,8 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, // Don't forget to properly update NodeTypeToString - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_GROUPSHARED_VARIABLE + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_DEFAULT, + D3D12_HLSL_NODE_TYPE_INVALID }; struct D3D12_HLSL_NODE { diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl index 27bd3c0313..f3a871f66e 100644 --- a/tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl +++ b/tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl @@ -18,9 +18,43 @@ struct A : C { ConstantBuffer b; [[oxc::fancy]] -void test(A a, float b) { - if(b) {} - else {} +void test(A a, uint b) { + + if(b) { float a0; } + else if(b != 1) { float a1; } + else { float a2; } + + do { float a3; } while(0); + + if(uint d = b ^ 23) { float a4; } + else if(uint d = b ^ 22) { float a5; } + else { float a6; } + + switch(uint d = b ^ 23) { + default: { float a7; break; } + } + + switch(b) { + case 0: { float a8; break; } + case 1: { float a9; break; } + default: break; + } + + while(false) { float a10; break; } + + for(int i = 0; i < 16; ++i) { + float a11; + } + + for(int i = 0, j = 0; i < 16; ++i, ++j) { + float a12; + } + + for(int i = 0, j = 0; bool k = i < 16; ++i, ++j) { + float a12; + } + + { float a13; } } namespace tst { @@ -47,6 +81,27 @@ namespace tst { // CHECK: "C", // CHECK: "test", // CHECK: "b", +// CHECK: "uint", +// CHECK: "a0", +// CHECK: "a1", +// CHECK: "a2", +// CHECK: "a3", +// CHECK: "d", +// CHECK: "a4", +// CHECK: "a5", +// CHECK: "a6", +// CHECK: "a7", +// CHECK: "a8", +// CHECK: "a9", +// CHECK: "a10", +// CHECK: "int", +// CHECK: "i", +// CHECK: "a11", +// CHECK: "j", +// CHECK: "a12", +// CHECK: "bool", +// CHECK: "k", +// CHECK: "a13", // CHECK: "tst" // CHECK: ], // CHECK: "StringsNonDebug": [ @@ -65,7 +120,7 @@ namespace tst { // CHECK: "NodeTypeId": 4, // CHECK: "LocalId": 0, // CHECK: "ParentId": -1, -// CHECK: "ChildCount": 17, +// CHECK: "ChildCount": 58, // CHECK: "ChildStart": 1 // CHECK: }, // CHECK: { @@ -157,7 +212,7 @@ namespace tst { // CHECK: "NodeTypeId": 1, // CHECK: "LocalId": 1, // CHECK: "ParentId": 0, -// CHECK: "ChildCount": 3, +// CHECK: "ChildCount": 44, // CHECK: "ChildStart": 13, // CHECK: "AnnotationStart": 0, // CHECK: "AnnotationCount": 1, @@ -184,23 +239,344 @@ namespace tst { // CHECK: "NodeType": "If", // CHECK: "NodeTypeId": 12, // CHECK: "LocalId": 0, -// CHECK: "ParentId": 12 +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 4, +// CHECK: "ChildStart": 16 // CHECK: }, // CHECK: { // CHECK: "NodeId": 16, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 15 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 17, +// CHECK: "NodeType": "If", +// CHECK: "NodeTypeId": 12, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 15, +// CHECK: "ChildCount": 2, +// CHECK: "ChildStart": 18 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 18, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 17 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 19, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 17 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 20, +// CHECK: "NodeType": "Do", +// CHECK: "NodeTypeId": 14, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 21 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 21, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 20 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 22, +// CHECK: "NodeType": "If", +// CHECK: "NodeTypeId": 12, +// CHECK: "LocalId": 2, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 6, +// CHECK: "ChildStart": 23 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 23, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 6, +// CHECK: "ParentId": 22 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 24, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 22 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 25, +// CHECK: "NodeType": "If", +// CHECK: "NodeTypeId": 12, +// CHECK: "LocalId": 3, +// CHECK: "ParentId": 22, +// CHECK: "ChildCount": 3, +// CHECK: "ChildStart": 26 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 26, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 6, +// CHECK: "ParentId": 25 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 27, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 25 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 28, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 25 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 29, +// CHECK: "NodeType": "Switch", +// CHECK: "NodeTypeId": 15, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 3, +// CHECK: "ChildStart": 30 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 30, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 6, +// CHECK: "ParentId": 29 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 31, +// CHECK: "NodeType": "Default", +// CHECK: "NodeTypeId": 20, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 29, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 32 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 32, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 31 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 33, +// CHECK: "NodeType": "Switch", +// CHECK: "NodeTypeId": 15, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 7, +// CHECK: "ChildStart": 34 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 34, +// CHECK: "NodeType": "Case", +// CHECK: "NodeTypeId": 19, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 33, +// CHECK: "ChildCount": 2, +// CHECK: "ChildStart": 35 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 35, +// CHECK: "NodeType": "Scope", +// CHECK: "NodeTypeId": 13, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 34, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 36 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 36, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 35 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 37, +// CHECK: "NodeType": "Case", +// CHECK: "NodeTypeId": 19, +// CHECK: "LocalId": 2, +// CHECK: "ParentId": 33, +// CHECK: "ChildCount": 2, +// CHECK: "ChildStart": 38 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 38, +// CHECK: "NodeType": "Scope", +// CHECK: "NodeTypeId": 13, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 37, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 39 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 39, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 38 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 40, +// CHECK: "NodeType": "Default", +// CHECK: "NodeTypeId": 20, +// CHECK: "LocalId": 3, +// CHECK: "ParentId": 33 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 41, +// CHECK: "NodeType": "While", +// CHECK: "NodeTypeId": 16, +// CHECK: "LocalId": 4, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 42 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 42, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 41 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 43, +// CHECK: "NodeType": "For", +// CHECK: "NodeTypeId": 17, +// CHECK: "LocalId": 5, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 2, +// CHECK: "ChildStart": 44 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 44, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 43 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 45, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 43 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 46, +// CHECK: "NodeType": "For", +// CHECK: "NodeTypeId": 17, +// CHECK: "LocalId": 6, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 3, +// CHECK: "ChildStart": 47 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 47, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 46 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 48, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 46 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 49, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 46 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 50, +// CHECK: "NodeType": "For", +// CHECK: "NodeTypeId": 17, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 4, +// CHECK: "ChildStart": 51 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 51, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 8, +// CHECK: "ParentId": 50 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 52, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 50 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 53, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 50 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 54, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 50 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 55, +// CHECK: "NodeType": "Scope", +// CHECK: "NodeTypeId": 13, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 56 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 56, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 55 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 57, // CHECK: "NodeType": "Namespace", // CHECK: "NodeTypeId": 4, // CHECK: "LocalId": 0, // CHECK: "ParentId": 0, // CHECK: "ChildCount": 1, -// CHECK: "ChildStart": 17 +// CHECK: "ChildStart": 58 // CHECK: }, // CHECK: { -// CHECK: "NodeId": 17, +// CHECK: "NodeId": 58, // CHECK: "NodeType": "Variable", // CHECK: "NodeTypeId": 5, // CHECK: "LocalId": 0, -// CHECK: "ParentId": 16 +// CHECK: "ParentId": 57 // CHECK: } // CHECK: ], // CHECK: "Registers": [ @@ -235,8 +611,8 @@ namespace tst { // CHECK: "TypeName": "A" // CHECK: }, // CHECK: "b": { -// CHECK: "TypeId": 0, -// CHECK: "TypeName": "float" +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "uint" // CHECK: } // CHECK: }, // CHECK: "ReturnType": { @@ -252,8 +628,8 @@ namespace tst { // CHECK: }, // CHECK: { // CHECK: "ParamName": "b", -// CHECK: "TypeId": 0, -// CHECK: "TypeName": "float" +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "uint" // CHECK: } // CHECK: ], // CHECK: "Enums": [ @@ -425,6 +801,18 @@ namespace tst { // CHECK: "TypeName": "float" // CHECK: } // CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 6, +// CHECK: "Name": "uint" +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 7, +// CHECK: "Name": "int" +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 8, +// CHECK: "Name": "bool" // CHECK: } // CHECK: ], // CHECK: "Buffers": [ @@ -462,8 +850,93 @@ namespace tst { // CHECK: { // CHECK: "Type": "If", // CHECK: "NodeId": 15, -// CHECK: "HasConditionVar": false, -// CHECK: "HasElse": true +// CHECK: "HasElse": true, +// CHECK: "NodesA": 1, +// CHECK: "NodesB": 3 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "If", +// CHECK: "NodeId": 17, +// CHECK: "HasElse": true, +// CHECK: "NodesA": 1, +// CHECK: "NodesB": 1 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "If", +// CHECK: "NodeId": 22, +// CHECK: "HasConditionVar": true, +// CHECK: "HasElse": true, +// CHECK: "NodesA": 1, +// CHECK: "NodesB": 4 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "If", +// CHECK: "NodeId": 25, +// CHECK: "HasConditionVar": true, +// CHECK: "HasElse": true, +// CHECK: "NodesA": 1, +// CHECK: "NodesB": 1 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "While", +// CHECK: "NodeId": 41, +// CHECK: "NodesB": 1 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "For", +// CHECK: "NodeId": 43, +// CHECK: "NodesA": 1, +// CHECK: "NodesB": 1 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "For", +// CHECK: "NodeId": 46, +// CHECK: "NodesA": 2, +// CHECK: "NodesB": 1 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "For", +// CHECK: "NodeId": 50, +// CHECK: "HasConditionVar": true, +// CHECK: "NodesA": 2, +// CHECK: "NodesB": 1 +// CHECK: } +// CHECK: ], +// CHECK: "IfSwitchStatements": [ +// CHECK: { +// CHECK: "Type": "Switch", +// CHECK: "NodeId": 29, +// CHECK: "HasConditionVar": true, +// CHECK: "HasElseOrDefault": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Switch", +// CHECK: "NodeId": 33, +// CHECK: "HasElseOrDefault": true +// CHECK: } +// CHECK: ], +// CHECK: "BranchStatements": [ +// CHECK: { +// CHECK: "Type": "Default", +// CHECK: "NodeId": 31, +// CHECK: "IsComplexCase": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Case", +// CHECK: "NodeId": 34, +// CHECK: "Type": "uint", +// CHECK: "Value": 0 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Case", +// CHECK: "NodeId": 37, +// CHECK: "Type": "uint", +// CHECK: "Value": 1 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Default", +// CHECK: "NodeId": 40, +// CHECK: "IsComplexCase": true // CHECK: } // CHECK: ] // CHECK: } diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl index 56e5bb4c36..64af7e3ba8 100644 --- a/tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl +++ b/tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl @@ -68,6 +68,18 @@ void test(uint b) { break; } + switch(b) { + case 0: + break; + default: + break; + } + + switch(b) { + default: + break; + } + switch(b) { case 0: { float c; @@ -85,6 +97,10 @@ void test(uint b) { float c; break; } + default: { + float c; + break; + } } } @@ -318,7 +334,7 @@ void test(uint b) { // CHECK: "Name": "c", // CHECK: "NodeType": "Variable", // CHECK: "Type": { -// CHECK: "Name": "float" +// CHECK: "Name": "float" // CHECK: } // CHECK: } // CHECK: ], @@ -326,24 +342,24 @@ void test(uint b) { // CHECK: { // CHECK: "NodeType": "If", // CHECK: "If": { -// CHECK: "Body": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" -// CHECK: } -// CHECK: } -// CHECK: ], -// CHECK: "Else": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" -// CHECK: } -// CHECK: } -// CHECK: ] +// CHECK: "Body": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Else": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] // CHECK: } // CHECK: } // CHECK: ] @@ -365,12 +381,149 @@ void test(uint b) { // CHECK: "Name": "uint" // CHECK: } // CHECK: } -// CHECK: } +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "Case", +// CHECK: "Case": { +// CHECK: "Type": "uint", +// CHECK: "Value": 0 +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] // CHECK: }, // CHECK: { // CHECK: "NodeType": "Switch", -// CHECK: "Switch": { -// CHECK: } +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "Case", +// CHECK: "Case": { +// CHECK: "Type": "uint", +// CHECK: "Value": 0 +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Default" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Switch", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "Default" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Switch", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "Case", +// CHECK: "Case": { +// CHECK: "Type": "uint", +// CHECK: "Value": 0 +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "Scope", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Case", +// CHECK: "Case": { +// CHECK: "Type": "uint", +// CHECK: "Value": 1 +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "Scope", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Case", +// CHECK: "Case": { +// CHECK: "Type": "uint", +// CHECK: "Value": 2 +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "Scope", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Case", +// CHECK: "Case": { +// CHECK: "Type": "uint", +// CHECK: "Value": 3 +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "Scope", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Default", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] // CHECK: } // CHECK: ] // CHECK: } diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 8b88f76f39..b800cc82e2 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -1455,6 +1455,31 @@ AddFunctionParameter(ASTContext &ASTCtx, QualType Type, Decl *Decl, return ReflectionErrorSuccess; } +static D3D12_HLSL_ENUM_TYPE GetEnumTypeFromQualType(ASTContext &ASTCtx, + QualType desugared) { + + const auto &semantics = ASTCtx.getTypeInfo(desugared); + + switch (semantics.Width) { + + default: + case 32: + return desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT + : D3D12_HLSL_ENUM_TYPE_INT; + + case 16: + return desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT16_T + : D3D12_HLSL_ENUM_TYPE_INT16_T; + + case 64: + return desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT64_T + : D3D12_HLSL_ENUM_TYPE_INT64_T; + } + + assert(false && "QualType of invalid type passed"); + return D3D12_HLSL_ENUM_TYPE_INT; +} + struct RecursiveStmtReflector : public StmtVisitor { ASTContext &ASTCtx; @@ -1563,11 +1588,140 @@ struct RecursiveStmtReflector : public StmtVisitor { if (LastError) return; - LastError = GenerateStatement( - ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, - ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, - D3D12_HLSL_NODE_TYPE_SWITCH, Switch->getConditionVariable(), - Switch->getBody(), nullptr, Switch); + uint32_t loc = uint32_t(Refl.IfSwitchStatements.size()); + + const SourceRange &sourceRange = Switch->getSourceRange(); + + uint32_t nodeId; + if (ReflectionError err = + PushNextNodeId(nodeId, Refl, SM, LangOpts, "", nullptr, + D3D12_HLSL_NODE_TYPE_SWITCH, ParentNodeId, loc, + &sourceRange, &FwdDecls)) { + LastError = err; + return; + } + + Refl.IfSwitchStatements.push_back(ReflectionIfSwitchStmt()); + + VarDecl *cond = Switch->getConditionVariable(); + + if (cond) { + + uint32_t typeId; + if (ReflectionError err = GenerateTypeInfo( + typeId, ASTCtx, Refl, cond->getType(), DefaultRowMaj)) { + LastError = err; + return; + } + + const SourceRange &sourceRange = cond->getSourceRange(); + + uint32_t nextNodeId; + if (ReflectionError err = + PushNextNodeId(nextNodeId, Refl, SM, LangOpts, cond->getName(), + cond, D3D12_HLSL_NODE_TYPE_VARIABLE, nodeId, + typeId, &sourceRange, &FwdDecls)) { + LastError = err; + return; + } + } + + Stmt *body = Switch->getBody(); + assert(body && "SwitchStmt has no body"); + + bool hasElseOrDefault = false; + + for (Stmt *child : body->children()) { + + const SwitchCase *switchCase = nullptr; + uint64_t caseValue = uint64_t(-1); + D3D12_HLSL_ENUM_TYPE valueType = D3D12_HLSL_ENUM_TYPE_INT; + D3D12_HLSL_NODE_TYPE nodeType = D3D12_HLSL_NODE_TYPE_INVALID; + + bool isComplexCase = true; + + if (const CaseStmt *caseStmt = dyn_cast(child)) { + + switchCase = caseStmt; + + llvm::APSInt result; + + if (caseStmt->getLHS()->isIntegerConstantExpr(result, ASTCtx)) { + caseValue = result.getZExtValue(); + + QualType desugared = caseStmt->getLHS()->getType(); + valueType = GetEnumTypeFromQualType(ASTCtx, desugared); + isComplexCase = false; + } + + else + caseValue = uint64_t(-1); + + nodeType = D3D12_HLSL_NODE_TYPE_CASE; + + } else if (const DefaultStmt *defaultStmt = + dyn_cast(child)) { + switchCase = defaultStmt; + hasElseOrDefault = true; + nodeType = D3D12_HLSL_NODE_TYPE_DEFAULT; + } + + if (!switchCase) + continue; + + uint32_t loc = uint32_t(Refl.BranchStatements.size()); + + const SourceRange &sourceRange = Switch->getSourceRange(); + + uint32_t childId; + if (ReflectionError err = + PushNextNodeId(childId, Refl, SM, LangOpts, "", nullptr, nodeType, + nodeId, loc, &sourceRange, &FwdDecls)) { + LastError = err; + return; + } + + Refl.BranchStatements.push_back(ReflectionBranchStmt()); + if (ReflectionError err = ReflectionBranchStmt::Initialize( + Refl.BranchStatements.back(), childId, false, isComplexCase, + valueType, caseValue)) { + LastError = err; + return; + } + + uint32_t parentSelf = ParentNodeId; + ParentNodeId = childId; + + auto firstIt = child->child_begin(); + auto it = firstIt; + + if (it != child->child_end()) { + + ++it; + + if (it == child->child_end() && isa(*firstIt)) { + for (Stmt *childChild : firstIt->children()) + if (ReflectionError err = TraverseStmt(childChild)) { + LastError = err; + return; + } + } + + else + for (Stmt *childChild : child->children()) + if (ReflectionError err = TraverseStmt(childChild)) { + LastError = err; + return; + } + } + + ParentNodeId = parentSelf; + } + + if(ReflectionError err = ReflectionIfSwitchStmt::Initialize(Refl.IfSwitchStatements[loc], nodeId, cond, hasElseOrDefault)) { + LastError = err; + return; + } } void VisitCompoundStmt(CompoundStmt *C) { @@ -1874,28 +2028,8 @@ class RecursiveReflector : public DeclVisitor { QualType enumType = ED->getIntegerType(); QualType desugared = enumType.getDesugaredType(ASTCtx); - const auto &semantics = ASTCtx.getTypeInfo(desugared); - - D3D12_HLSL_ENUM_TYPE type; - - switch (semantics.Width) { - - default: - case 32: - type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT - : D3D12_HLSL_ENUM_TYPE_INT; - break; - - case 16: - type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT16_T - : D3D12_HLSL_ENUM_TYPE_INT16_T; - break; - case 64: - type = desugared->isUnsignedIntegerType() ? D3D12_HLSL_ENUM_TYPE_UINT64_T - : D3D12_HLSL_ENUM_TYPE_INT64_T; - break; - } + D3D12_HLSL_ENUM_TYPE type = GetEnumTypeFromQualType(ASTCtx, desugared); Refl.Enums.push_back({nodeId, type}); } diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index 42665aba81..a183e88fdb 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -196,6 +196,9 @@ struct HLSLReflectionDataHeader { uint32_t Parameters; uint32_t Statements; + uint32_t IfSwitchStatements; + + uint32_t BranchStatements; uint32_t Pad; }; @@ -472,40 +475,44 @@ void ReflectionData::Dump(std::vector &Bytes) const { Advance(toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, TypeSymbols, - Buffers, Parameters, Statements); + Buffers, Parameters, Statements, IfSwitchStatements, + BranchStatements); Bytes.resize(toReserve); toReserve = 0; - UnsafeCast(Bytes, - toReserve) = {ReflectionDataMagic, - ReflectionDataVersion, - uint16_t(Sources.size()), - Features, - uint32_t(StringsNonDebug.size()), - uint32_t(Strings.size()), - uint32_t(Nodes.size()), - uint32_t(Registers.size()), - uint32_t(Functions.size()), - uint32_t(Enums.size()), - uint32_t(EnumValues.size()), - uint32_t(Annotations.size()), - uint32_t(Arrays.size()), - uint32_t(ArraySizes.size()), - uint32_t(MemberTypeIds.size()), - uint32_t(Types.size()), - uint32_t(Buffers.size()), - uint32_t(TypeList.size()), - uint32_t(Parameters.size()), - uint32_t(Statements.size())}; + UnsafeCast(Bytes, toReserve) = { + ReflectionDataMagic, + ReflectionDataVersion, + uint16_t(Sources.size()), + Features, + uint32_t(StringsNonDebug.size()), + uint32_t(Strings.size()), + uint32_t(Nodes.size()), + uint32_t(Registers.size()), + uint32_t(Functions.size()), + uint32_t(Enums.size()), + uint32_t(EnumValues.size()), + uint32_t(Annotations.size()), + uint32_t(Arrays.size()), + uint32_t(ArraySizes.size()), + uint32_t(MemberTypeIds.size()), + uint32_t(Types.size()), + uint32_t(Buffers.size()), + uint32_t(TypeList.size()), + uint32_t(Parameters.size()), + uint32_t(Statements.size()), + uint32_t(IfSwitchStatements.size()), + uint32_t(BranchStatements.size())}; toReserve += sizeof(HLSLReflectionDataHeader); Append(Bytes, toReserve, Strings, StringsNonDebug, Sources, Nodes, NodeSymbols, Registers, Functions, Enums, EnumValues, Annotations, ArraySizes, Arrays, MemberTypeIds, TypeList, MemberNameIds, Types, - TypeSymbols, Buffers, Parameters, Statements); + TypeSymbols, Buffers, Parameters, Statements, IfSwitchStatements, + BranchStatements); } D3D_CBUFFER_TYPE ReflectionData::GetBufferType(uint8_t Type) { @@ -567,7 +574,9 @@ ReflectionData::Deserialize(const std::vector &Bytes, Arrays, header.Arrays, MemberTypeIds, header.Members, TypeList, header.TypeListCount, MemberNameIds, memberSymbolCount, Types, header.Types, TypeSymbols, typeSymbolCount, Buffers, header.Buffers, - Parameters, header.Parameters, Statements, header.Statements)) + Parameters, header.Parameters, Statements, header.Statements, + IfSwitchStatements, header.IfSwitchStatements, BranchStatements, + header.BranchStatements)) return err; // Validation errors to prevent accessing invalid data @@ -638,6 +647,17 @@ ReflectionData::Deserialize(const std::vector &Bytes, break; + case D3D12_HLSL_NODE_TYPE_DEFAULT: + case D3D12_HLSL_NODE_TYPE_CASE: + + maxValue = header.BranchStatements; + + if (Nodes[node.GetParentId()].GetNodeType() != + D3D12_HLSL_NODE_TYPE_SWITCH) + return HLSL_REFL_ERR( + "Node is a default/case but doesn't belong to a switch", i); + break; + case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: case D3D12_HLSL_NODE_TYPE_IF: @@ -645,10 +665,12 @@ ReflectionData::Deserialize(const std::vector &Bytes, case D3D12_HLSL_NODE_TYPE_WHILE: case D3D12_HLSL_NODE_TYPE_SWITCH: - maxValue = node.GetNodeType() != D3D12_HLSL_NODE_TYPE_SCOPE && - node.GetNodeType() != D3D12_HLSL_NODE_TYPE_DO - ? header.Statements - : 1; + maxValue = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_SWITCH + ? header.IfSwitchStatements + : (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_SCOPE && + node.GetNodeType() != D3D12_HLSL_NODE_TYPE_DO + ? header.Statements + : 1); switch (Nodes[node.GetParentId()].GetNodeType()) { case D3D12_HLSL_NODE_TYPE_FUNCTION: @@ -658,6 +680,11 @@ ReflectionData::Deserialize(const std::vector &Bytes, case D3D12_HLSL_NODE_TYPE_FOR: case D3D12_HLSL_NODE_TYPE_WHILE: case D3D12_HLSL_NODE_TYPE_SWITCH: + case D3D12_HLSL_NODE_TYPE_CASE: + case D3D12_HLSL_NODE_TYPE_DEFAULT: + //TODO: case D3D12_HLSL_NODE_TYPE_IF_START: + //TODO: case D3D12_HLSL_NODE_TYPE_IF_ELSE: + //TODO: case D3D12_HLSL_NODE_TYPE_ELSE: break; default: @@ -696,15 +723,18 @@ ReflectionData::Deserialize(const std::vector &Bytes, return HLSL_REFL_ERR("Node is a parameter, typedef, variable or " "static variable but also has children", i); - - [[fallthrough]]; + break; case D3D12_HLSL_NODE_TYPE_IF: case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: case D3D12_HLSL_NODE_TYPE_FOR: case D3D12_HLSL_NODE_TYPE_WHILE: - case D3D12_HLSL_NODE_TYPE_SWITCH: + case D3D12_HLSL_NODE_TYPE_DEFAULT: + case D3D12_HLSL_NODE_TYPE_CASE: + // TODO: case D3D12_HLSL_NODE_TYPE_IF_START: + // TODO: case D3D12_HLSL_NODE_TYPE_IF_ELSE: + // TODO: case D3D12_HLSL_NODE_TYPE_ELSE: if (node.GetChildCount()) validateChildren.push_back(i); } @@ -816,7 +846,25 @@ ReflectionData::Deserialize(const std::vector &Bytes, Nodes[enumVal.NodeId].GetLocalId() != i || Nodes[Nodes[enumVal.NodeId].GetParentId()].GetNodeType() != D3D12_HLSL_NODE_TYPE_ENUM) - return HLSL_REFL_ERR("Enum points to an invalid nodeId", i); + return HLSL_REFL_ERR("Enum value points to an invalid nodeId", i); + + uint64_t maxVal = uint64_t(-1); + ReflectionNode &parent = Nodes[Nodes[enumVal.NodeId].GetParentId()]; + + switch (Enums[parent.GetLocalId()].Type) { + case D3D12_HLSL_ENUM_TYPE_UINT: + case D3D12_HLSL_ENUM_TYPE_INT: + maxVal = uint32_t(-1); + break; + + case D3D12_HLSL_ENUM_TYPE_UINT16_T: + case D3D12_HLSL_ENUM_TYPE_INT16_T: + maxVal = uint16_t(-1); + break; + } + + if (uint64_t(enumVal.Value) > maxVal) + return HLSL_REFL_ERR("Enum value is invalid", i); } for (uint32_t i = 0; i < header.Arrays; ++i) { @@ -907,6 +955,11 @@ ReflectionData::Deserialize(const std::vector &Bytes, case D3D12_HLSL_NODE_TYPE_FOR: case D3D12_HLSL_NODE_TYPE_WHILE: case D3D12_HLSL_NODE_TYPE_SWITCH: + case D3D12_HLSL_NODE_TYPE_DEFAULT: + case D3D12_HLSL_NODE_TYPE_CASE: + //TODO: case D3D12_HLSL_NODE_TYPE_IF_START: + //TODO: case D3D12_HLSL_NODE_TYPE_IF_ELSE: + //TODO: case D3D12_HLSL_NODE_TYPE_ELSE: break; default: return HLSL_REFL_ERR( @@ -938,17 +991,155 @@ ReflectionData::Deserialize(const std::vector &Bytes, "Statement has condition variable but first child is not a variable", i); - switch (Nodes[Stmt.GetNodeId()].GetNodeType()) { + switch (node.GetNodeType()) { case D3D12_HLSL_NODE_TYPE_IF: case D3D12_HLSL_NODE_TYPE_WHILE: case D3D12_HLSL_NODE_TYPE_FOR: - case D3D12_HLSL_NODE_TYPE_SWITCH: break; default: return HLSL_REFL_ERR("Statement has invalid node type", i); } } + for (uint32_t i = 0; i < header.IfSwitchStatements; ++i) { + + const ReflectionIfSwitchStmt &Stmt = IfSwitchStatements[i]; + + if (Stmt.GetNodeId() >= header.Nodes || + Nodes[Stmt.GetNodeId()].GetLocalId() != i) + return HLSL_REFL_ERR("IfSwitchStmt points to an invalid nodeId", i); + + bool condVar = Stmt.HasConditionVar(); + uint32_t minParamCount = condVar + Stmt.HasElseOrDefault(); + const ReflectionNode &node = Nodes[Stmt.GetNodeId()]; + + if (node.GetChildCount() < minParamCount) + return HLSL_REFL_ERR("IfSwitchStmt didn't have required child nodes", i); + + if (condVar && node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF) + return HLSL_REFL_ERR("If statement can't have a conditional node in root", + i); + + if (condVar && Nodes[Stmt.GetNodeId() + 1].GetNodeType() != + D3D12_HLSL_NODE_TYPE_VARIABLE) + return HLSL_REFL_ERR( + "Statement has condition variable but first child is not a variable", + i); + + switch (node.GetNodeType()) { + case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_SWITCH: + break; + default: + return HLSL_REFL_ERR("IfSwitchStmt has invalid node type", i); + } + + // Ensure there's only one default/else and the first is the IF_FIRST node. + + uint32_t nodeStart = Stmt.GetNodeId() + 1 + condVar; + uint32_t nodeEnd = Stmt.GetNodeId() + node.GetChildCount(); + bool hasSingleNode = + false; // Else or default where you're only allowed to have one + + for (uint32_t j = nodeStart, k = 0; j < nodeEnd; ++j, ++k) { + + const ReflectionNode &child = Nodes[j]; + + bool isSingleNode = child.GetNodeType() == D3D12_HLSL_NODE_TYPE_DEFAULT; //TODO: IF: ELSE + + if (isSingleNode) { + + if (hasSingleNode) + return HLSL_REFL_ERR("IfSwitchStmt already has default/else", i); + + hasSingleNode = true; + } + + else { + + //TODO: if (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF) + // expectedType = !k ? IF_START : ELSE_IF; + + bool invalid = child.GetNodeType() != D3D12_HLSL_NODE_TYPE_CASE; + + if (invalid) + return HLSL_REFL_ERR("IfSwitchStmt has an invalid member", i); + } + + j += child.GetChildCount(); + } + } + + for (uint32_t i = 0; i < header.BranchStatements; ++i) { + + const ReflectionBranchStmt &Stmt = BranchStatements[i]; + + if (Stmt.GetNodeId() >= header.Nodes || + Nodes[Stmt.GetNodeId()].GetLocalId() != i) + return HLSL_REFL_ERR("BranchStatements points to an invalid nodeId", i); + + if (Stmt.GetValueType() < D3D12_HLSL_ENUM_TYPE_UINT || + Stmt.GetValueType() > D3D12_HLSL_ENUM_TYPE_INT16_T) + return HLSL_REFL_ERR("BranchStatement has an invalid value type", i); + + bool condVar = Stmt.HasConditionVar(); + uint32_t minParamCount = condVar; + const ReflectionNode &node = Nodes[Stmt.GetNodeId()]; + + if (node.GetChildCount() < minParamCount) + return HLSL_REFL_ERR("IfSwitchStmt didn't have required child nodes", i); + + // TODO: Else + + if (condVar && (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_DEFAULT || + node.GetNodeType() == D3D12_HLSL_NODE_TYPE_CASE)) + return HLSL_REFL_ERR("If statement can't have a conditional node in root", + i); + + if (condVar && Nodes[Stmt.GetNodeId() + 1].GetNodeType() != + D3D12_HLSL_NODE_TYPE_VARIABLE) + return HLSL_REFL_ERR( + "Statement has condition variable but first child is not a variable", + i); + + switch (node.GetNodeType()) { + case D3D12_HLSL_NODE_TYPE_CASE: + case D3D12_HLSL_NODE_TYPE_DEFAULT: + // TODO: case D3D12_HLSL_NODE_TYPE_IF_START: + // TODO: case D3D12_HLSL_NODE_TYPE_ELSE_IF: + // TODO: case D3D12_HLSL_NODE_TYPE_ELSE: + break; + default: + return HLSL_REFL_ERR("IfSwitchStmt has invalid node type", i); + } + + if (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_CASE && + !Stmt.IsComplexCase()) { + + uint64_t maxVal = uint64_t(-1); + + switch (Stmt.GetValueType()) { + + case D3D12_HLSL_ENUM_TYPE_UINT: + case D3D12_HLSL_ENUM_TYPE_INT: + maxVal = uint32_t(-1); + break; + + case D3D12_HLSL_ENUM_TYPE_UINT16_T: + case D3D12_HLSL_ENUM_TYPE_INT16_T: + maxVal = uint16_t(-1); + break; + } + + if (Stmt.GetValue() > maxVal) + return HLSL_REFL_ERR("IfSwitchStmt is out of bounds for the value type", + i); + } + + else if (Stmt.GetValue() != uint64_t(-1)) + return HLSL_REFL_ERR("IfSwitchStmt should have -1 as value", i); + } + for (uint32_t i = 0; i < header.Types; ++i) { const ReflectionVariableType &type = Types[i]; diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 58ca9e4cbc..3f71dafbe4 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -297,7 +297,9 @@ static const char *NodeTypeToString(D3D12_HLSL_NODE_TYPE Type) { "Switch", "While", "For", - "GroupsharedVariable"}; + "GroupsharedVariable", + "Case", + "Default"}; return arr[uint32_t(Type)]; } @@ -920,6 +922,29 @@ static void PrintFunction(JsonWriter &Json, const ReflectionData &Reflection, } } +static void PrintValue(JsonWriter &Json, D3D12_HLSL_ENUM_TYPE type, uint64_t v, + const char *Name = "Value") { + + switch (type) { + + case D3D12_HLSL_ENUM_TYPE_INT: + Json.IntField("Value", int32_t(uint32_t(v))); + break; + + case D3D12_HLSL_ENUM_TYPE_INT64_T: + Json.IntField("Value", int64_t(v)); + break; + + case D3D12_HLSL_ENUM_TYPE_INT16_T: + Json.IntField("Value", int16_t(uint16_t(v))); + break; + + default: + Json.UIntField("Value", v); + break; + } +} + static void PrintEnumValue(JsonWriter &Json, const ReflectionData &Reflection, uint32_t NodeId, const ReflectionPrintSettings &Settings) { @@ -931,16 +956,7 @@ static void PrintEnumValue(JsonWriter &Json, const ReflectionData &Reflection, const ReflectionNode &parent = Reflection.Nodes[child.GetParentId()]; const ReflectionEnumeration &enm = Reflection.Enums[parent.GetLocalId()]; - switch (enm.Type) { - case D3D12_HLSL_ENUM_TYPE_INT: - case D3D12_HLSL_ENUM_TYPE_INT64_T: - case D3D12_HLSL_ENUM_TYPE_INT16_T: - Json.IntField("Value", val.Value); - break; - - default: - Json.UIntField("Value", uint64_t(val.Value)); - } + PrintValue(Json, enm.Type, val.Value); bool hasSymbols = Reflection.Features & D3D12_HLSL_REFLECTION_FEATURE_SYMBOL_INFO; @@ -1067,11 +1083,12 @@ static void PrintStatement(const ReflectionData &Reflection, uint32_t nodesA = Stmt.GetNodeCount(); uint32_t nodesB = node.GetChildCount() - nodesA - Stmt.HasConditionVar(); - Json.BoolField("HasConditionVar", Stmt.HasConditionVar()); + if (Stmt.HasConditionVar()) + Json.BoolField("HasConditionVar", Stmt.HasConditionVar()); bool isIf = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF; - if (isIf) + if (isIf && Stmt.HasElse()) Json.BoolField("HasElse", Stmt.HasElse()); if (nodesA) @@ -1081,6 +1098,32 @@ static void PrintStatement(const ReflectionData &Reflection, Json.UIntField("NodesB", nodesB); } +static void PrintIfSwitchStatement(const ReflectionData &Reflection, + const ReflectionIfSwitchStmt &Stmt, + JsonWriter &Json) { + + if (Stmt.HasConditionVar()) + Json.BoolField("HasConditionVar", Stmt.HasConditionVar()); + + if (Stmt.HasElseOrDefault()) + Json.BoolField("HasElseOrDefault", Stmt.HasElseOrDefault()); +} + +static void PrintBranchStatement(const ReflectionData &Reflection, + const ReflectionBranchStmt &Stmt, + JsonWriter &Json) { + + if (Stmt.HasConditionVar()) + Json.BoolField("HasConditionVar", Stmt.HasConditionVar()); + + if (!Stmt.IsComplexCase()) { + Json.StringField("Type", EnumTypeToString(Stmt.GetValueType())); + PrintValue(Json, Stmt.GetValueType(), Stmt.GetValue()); + } + + else Json.BoolField("IsComplexCase", Stmt.IsComplexCase()); +} + uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, JsonWriter &Json, const ReflectionPrintSettings &Settings); @@ -1145,6 +1188,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, bool recurseType = false; const char *stmtType = nullptr; + const char *switchIfType = nullptr; switch (nodeType) { @@ -1220,12 +1264,26 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, break; + case D3D12_HLSL_NODE_TYPE_CASE: + + Json.Object( + "Case", [&node, &Reflection, &Json, &Settings, &childrenToSkip]() { + const ReflectionBranchStmt &branch = + Reflection.BranchStatements[node.GetLocalId()]; + if (!branch.IsComplexCase()) { + Json.StringField("Type", EnumTypeToString(branch.GetValueType())); + PrintValue(Json, branch.GetValueType(), branch.GetValue()); + } + }); + + break; + case D3D12_HLSL_NODE_TYPE_IF: stmtType = "If"; break; case D3D12_HLSL_NODE_TYPE_SWITCH: - stmtType = "Switch"; + switchIfType = "Switch"; break; case D3D12_HLSL_NODE_TYPE_FOR: @@ -1240,7 +1298,6 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, // If; turns into ("Condition"), ("Body"), ("Else") // While; turns into ("Condition"), ("Body") // For; turns into ("Condition"), ("Init"), ("Body") - // Switch; turns into ("Condition"), ("Body") if (stmtType) { @@ -1284,6 +1341,34 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, }); } + // Switch; turns into ("Condition"), ("Case": []) + // If; turns into "Ifs": [] + + else if (switchIfType) { + + const ReflectionIfSwitchStmt &stmt = + Reflection.IfSwitchStatements[node.GetLocalId()]; + + if (stmt.HasConditionVar()) + Json.Object(switchIfType, [&stmt, &Reflection, &Json, &Settings, NodeId, + &childrenToSkip, nodeType, hasSymbols]() { + uint32_t start = NodeId + 1; + + if (stmt.HasConditionVar()) + Json.Object("Condition", [NodeId, &Reflection, &Json, &start, + &Settings, hasSymbols]() { + if (hasSymbols) + PrintSymbol(Json, Reflection, Reflection.NodeSymbols[start], + Settings, false, true); + + start += PrintNodeRecursive(Reflection, start, Json, Settings); + ++start; + }); + + childrenToSkip = start - NodeId - 1; + }); + } + // Children uint32_t start = NodeId + 1 + childrenToSkip; @@ -1471,6 +1556,32 @@ std::string ReflectionData::ToJson(bool HideFileInfo, PrintStatement(*this, stat, json); } }); + + json.Array("IfSwitchStatements", [this, &json] { + for (uint32_t i = 0; i < uint32_t(IfSwitchStatements.size()); ++i) { + + const ReflectionIfSwitchStmt &stat = IfSwitchStatements[i]; + JsonWriter::ObjectScope valueRoot(json); + json.StringField( + "Type", NodeTypeToString(Nodes[stat.GetNodeId()].GetNodeType())); + json.UIntField("NodeId", stat.GetNodeId()); + + PrintIfSwitchStatement(*this, stat, json); + } + }); + + json.Array("BranchStatements", [this, &json] { + for (uint32_t i = 0; i < uint32_t(BranchStatements.size()); ++i) { + + const ReflectionBranchStmt &stat = BranchStatements[i]; + JsonWriter::ObjectScope valueRoot(json); + json.StringField( + "Type", NodeTypeToString(Nodes[stat.GetNodeId()].GetNodeType())); + json.UIntField("NodeId", stat.GetNodeId()); + + PrintBranchStatement(*this, stat, json); + } + }); } else From fee7be591b24dc771d81e55a310be3db3a2a0c11 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Thu, 13 Nov 2025 02:32:41 +0100 Subject: [PATCH 119/126] Clang format --- include/dxc/dxcreflect.h | 18 +++---- .../dxcreflection/dxcreflection_from_ast.cpp | 25 ++++----- .../tools/dxcreflection/dxcreflector.cpp | 54 +++++++++---------- .../DxcReflectionContainer.cpp | 22 ++++---- .../DxcReflectionJson.cpp | 15 +++--- tools/clang/tools/dxreflector/dxreflector.cpp | 2 +- .../unittests/HLSLTestLib/FileCheckerTest.cpp | 4 +- 7 files changed, 70 insertions(+), 70 deletions(-) diff --git a/include/dxc/dxcreflect.h b/include/dxc/dxcreflect.h index 29cbace06c..42b2728118 100644 --- a/include/dxc/dxcreflect.h +++ b/include/dxc/dxcreflect.h @@ -146,10 +146,10 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_INTERFACE, D3D12_HLSL_NODE_TYPE_PARAMETER, - // Control flow (Stmts or SwitchIfStmt), for full inspection of what variables exist where and - // scopes + // Control flow (Stmts or SwitchIfStmt), for full inspection of what variables + // exist where and scopes - D3D12_HLSL_NODE_TYPE_IF, //TODO: Rename to if root + D3D12_HLSL_NODE_TYPE_IF, // TODO: Rename to if root D3D12_HLSL_NODE_TYPE_SCOPE, D3D12_HLSL_NODE_TYPE_DO, D3D12_HLSL_NODE_TYPE_SWITCH, @@ -163,9 +163,9 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_CASE, D3D12_HLSL_NODE_TYPE_DEFAULT, - //D3D12_HLSL_NODE_TYPE_IF_FIRST, - //D3D12_HLSL_NODE_TYPE_ELSE_IF, - //D3D12_HLSL_NODE_TYPE_ELSE, + // D3D12_HLSL_NODE_TYPE_IF_FIRST, + // D3D12_HLSL_NODE_TYPE_ELSE_IF, + // D3D12_HLSL_NODE_TYPE_ELSE, // TODO: D3D12_HLSL_NODE_TYPE_USING, @@ -375,9 +375,9 @@ struct IHLSLReflector : public IUnknown { virtual HRESULT STDMETHODCALLTYPE ToBlob(IHLSLReflectionData *reflection, IDxcBlob **ppResult) = 0; - virtual HRESULT STDMETHODCALLTYPE ToString( - IHLSLReflectionData *reflection, ReflectorFormatSettings Settings, - IDxcBlobEncoding **ppResult) = 0; + virtual HRESULT STDMETHODCALLTYPE ToString(IHLSLReflectionData *reflection, + ReflectorFormatSettings Settings, + IDxcBlobEncoding **ppResult) = 0; }; #endif diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index b800cc82e2..70fe3e3eca 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -583,7 +583,7 @@ static DxcRegisterTypeInfo GetRegisterTypeInfo(ASTContext &ASTCtx, [[nodiscard]] static ReflectionError CollectUnderlyingArraySizes(QualType &T, std::vector &Out, uint64_t &FlatSize) { - + T = T.getNonReferenceType(); std::vector local; @@ -609,13 +609,12 @@ CollectUnderlyingArraySizes(QualType &T, std::vector &Out, return err; } - if (const TemplateSpecializationType *ts = + if (const TemplateSpecializationType *ts = dyn_cast(T)) { QualType desugared = ts->desugar().getNonReferenceType(); if (desugared != T) { T = desugared; - if (ReflectionError err = - CollectUnderlyingArraySizes(T, Out, FlatSize)) + if (ReflectionError err = CollectUnderlyingArraySizes(T, Out, FlatSize)) return err; } } @@ -1625,7 +1624,7 @@ struct RecursiveStmtReflector : public StmtVisitor { return; } } - + Stmt *body = Switch->getBody(); assert(body && "SwitchStmt has no body"); @@ -1718,7 +1717,8 @@ struct RecursiveStmtReflector : public StmtVisitor { ParentNodeId = parentSelf; } - if(ReflectionError err = ReflectionIfSwitchStmt::Initialize(Refl.IfSwitchStatements[loc], nodeId, cond, hasElseOrDefault)) { + if (ReflectionError err = ReflectionIfSwitchStmt::Initialize( + Refl.IfSwitchStatements[loc], nodeId, cond, hasElseOrDefault)) { LastError = err; return; } @@ -2227,10 +2227,11 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, return Reflector.TraverseDeclContext(); } -[[nodiscard]] ReflectionError HLSLReflectionDataFromAST( - ReflectionData &Result, CompilerInstance &Compiler, - TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, - D3D12_HLSL_REFLECTION_FEATURE Features, bool DefaultRowMaj) { +[[nodiscard]] ReflectionError +HLSLReflectionDataFromAST(ReflectionData &Result, CompilerInstance &Compiler, + TranslationUnitDecl &Ctx, uint32_t AutoBindingSpace, + D3D12_HLSL_REFLECTION_FEATURE Features, + bool DefaultRowMaj) { DiagnosticsEngine &Diags = Ctx.getParentASTContext().getDiagnostics(); const SourceManager &SM = Compiler.getSourceManager(); @@ -2245,8 +2246,8 @@ RecursiveReflectHLSL(const DeclContext &Ctx, ASTContext &ASTCtx, if (ReflectionError err = ReflectionNodeSymbol::Initialize( Result.NodeSymbols[0], 0, uint16_t(-1), 0, 0, 0, 0)) { - llvm::errs() - << "HLSLReflectionDataFromAST: Failed to add root symbol: " << err; + llvm::errs() << "HLSLReflectionDataFromAST: Failed to add root symbol: " + << err; Result = {}; return err; } diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index a6dff9659b..68b416d12a 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -42,8 +42,8 @@ #include "dxc/Support/dxcfilesystem.h" #include "dxc/dxcapi.internal.h" -#include "dxc/dxcreflect.h" #include "dxc/DxcReflection/DxcReflectionContainer.h" +#include "dxc/dxcreflect.h" extern "C" const IID IID_IHLSLReflectionData = { 0x7016f834, @@ -669,7 +669,7 @@ struct HLSLReflectionData : public IHLSLReflectionData { HLSLReflectionData() : m_refCount(1) {} - //TODO: This function needs another look definitely + // TODO: This function needs another look definitely void Finalize() { Data.GenerateNameLookupTable(); @@ -698,8 +698,8 @@ struct HLSLReflectionData : public IHLSLReflectionData { functionParameters.push_back(i); } - // Filter out backward/fwd declarations for structs, unions, interfaces, functions, - // enums + // Filter out backward/fwd declarations for structs, unions, interfaces, + // functions, enums if (node.IsFwdDeclare()) { ChildCountsNonRecursive[i] = uint32_t(ChildrenNonRecursive[i].size()); @@ -794,35 +794,30 @@ struct HLSLReflectionData : public IHLSLReflectionData { HLSLReflectionData &operator=(HLSLReflectionData &&moved) = delete; // IUnknown - - STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject) override - { - if (!ppvObject) return E_POINTER; - - if (riid == IID_IUnknown || riid == IID_IHLSLReflectionData) - { - *ppvObject = static_cast(this); - AddRef(); - return S_OK; - } - *ppvObject = nullptr; - return E_NOINTERFACE; - } + STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject) override { + if (!ppvObject) + return E_POINTER; - STDMETHOD_(ULONG, AddRef)() override - { - return ++m_refCount; + if (riid == IID_IUnknown || riid == IID_IHLSLReflectionData) { + *ppvObject = static_cast(this); + AddRef(); + return S_OK; + } + + *ppvObject = nullptr; + return E_NOINTERFACE; } + STDMETHOD_(ULONG, AddRef)() override { return ++m_refCount; } + STDMETHOD_(ULONG, Release)() override { - ULONG count = --m_refCount; - if (!count) - delete this; - return count; + ULONG count = --m_refCount; + if (!count) + delete this; + return count; } - // Conversion of IReflection structs to D3D12_HLSL standardized structs STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_HLSL_REFLECTION_DESC *pDesc) override { @@ -1836,10 +1831,11 @@ class DxcReflector : public IHLSLReflector, public IDxcLangExtensions3 { return E_UNEXPECTED; DxcThreadMalloc TM(m_pMalloc); - std::string str = refl->Data.ToJson(!Settings.PrintFileInfo, Settings.IsHumanReadable); + std::string str = + refl->Data.ToJson(!Settings.PrintFileInfo, Settings.IsHumanReadable); - return DxcCreateBlob(str.c_str(), str.size(), false, true, true, - CP_UTF8, DxcGetThreadMallocNoRef(), ppResult); + return DxcCreateBlob(str.c_str(), str.size(), false, true, true, CP_UTF8, + DxcGetThreadMallocNoRef(), ppResult); } }; diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index a183e88fdb..47f0d4ae43 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -545,7 +545,8 @@ ReflectionData::Deserialize(const std::vector &Bytes, uint64_t off = 0; HLSLReflectionDataHeader header; - if (ReflectionError err = Consume(Bytes, off, header)) + if (ReflectionError err = + Consume(Bytes, off, header)) return err; if (header.MagicNumber != ReflectionDataMagic) @@ -682,9 +683,9 @@ ReflectionData::Deserialize(const std::vector &Bytes, case D3D12_HLSL_NODE_TYPE_SWITCH: case D3D12_HLSL_NODE_TYPE_CASE: case D3D12_HLSL_NODE_TYPE_DEFAULT: - //TODO: case D3D12_HLSL_NODE_TYPE_IF_START: - //TODO: case D3D12_HLSL_NODE_TYPE_IF_ELSE: - //TODO: case D3D12_HLSL_NODE_TYPE_ELSE: + // TODO: case D3D12_HLSL_NODE_TYPE_IF_START: + // TODO: case D3D12_HLSL_NODE_TYPE_IF_ELSE: + // TODO: case D3D12_HLSL_NODE_TYPE_ELSE: break; default: @@ -957,9 +958,9 @@ ReflectionData::Deserialize(const std::vector &Bytes, case D3D12_HLSL_NODE_TYPE_SWITCH: case D3D12_HLSL_NODE_TYPE_DEFAULT: case D3D12_HLSL_NODE_TYPE_CASE: - //TODO: case D3D12_HLSL_NODE_TYPE_IF_START: - //TODO: case D3D12_HLSL_NODE_TYPE_IF_ELSE: - //TODO: case D3D12_HLSL_NODE_TYPE_ELSE: + // TODO: case D3D12_HLSL_NODE_TYPE_IF_START: + // TODO: case D3D12_HLSL_NODE_TYPE_IF_ELSE: + // TODO: case D3D12_HLSL_NODE_TYPE_ELSE: break; default: return HLSL_REFL_ERR( @@ -1045,7 +1046,8 @@ ReflectionData::Deserialize(const std::vector &Bytes, const ReflectionNode &child = Nodes[j]; - bool isSingleNode = child.GetNodeType() == D3D12_HLSL_NODE_TYPE_DEFAULT; //TODO: IF: ELSE + bool isSingleNode = + child.GetNodeType() == D3D12_HLSL_NODE_TYPE_DEFAULT; // TODO: IF: ELSE if (isSingleNode) { @@ -1057,8 +1059,8 @@ ReflectionData::Deserialize(const std::vector &Bytes, else { - //TODO: if (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF) - // expectedType = !k ? IF_START : ELSE_IF; + // TODO: if (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF) + // expectedType = !k ? IF_START : ELSE_IF; bool invalid = child.GetNodeType() != D3D12_HLSL_NODE_TYPE_CASE; diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 3f71dafbe4..9016938068 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -481,8 +481,8 @@ struct ReflectionPrintSettings { static void PrintSymbol(JsonWriter &Json, const ReflectionData &Reflection, const ReflectionNodeSymbol &Sym, - const ReflectionPrintSettings &Settings, - bool MuteName, bool ShowOnlyName = false) { + const ReflectionPrintSettings &Settings, bool MuteName, + bool ShowOnlyName = false) { if (Sym.GetNameId() && !MuteName) { @@ -767,8 +767,8 @@ static void PrintType(const ReflectionData &Reflection, uint32_t TypeId, const ReflectionVariableType &type = Reflection.Types[TypeId]; - PrintTypeName(Reflection, TypeId, HasSymbols, Settings, Json, - NameForTypeName, true); + PrintTypeName(Reflection, TypeId, HasSymbols, Settings, Json, NameForTypeName, + true); if (type.GetBaseClass() != uint32_t(-1)) Json.Object("BaseClass", @@ -1110,8 +1110,8 @@ static void PrintIfSwitchStatement(const ReflectionData &Reflection, } static void PrintBranchStatement(const ReflectionData &Reflection, - const ReflectionBranchStmt &Stmt, - JsonWriter &Json) { + const ReflectionBranchStmt &Stmt, + JsonWriter &Json) { if (Stmt.HasConditionVar()) Json.BoolField("HasConditionVar", Stmt.HasConditionVar()); @@ -1121,7 +1121,8 @@ static void PrintBranchStatement(const ReflectionData &Reflection, PrintValue(Json, Stmt.GetValueType(), Stmt.GetValue()); } - else Json.BoolField("IsComplexCase", Stmt.IsComplexCase()); + else + Json.BoolField("IsComplexCase", Stmt.IsComplexCase()); } uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, diff --git a/tools/clang/tools/dxreflector/dxreflector.cpp b/tools/clang/tools/dxreflector/dxreflector.cpp index 16f8c6aee9..613f8eaebf 100644 --- a/tools/clang/tools/dxreflector/dxreflector.cpp +++ b/tools/clang/tools/dxreflector/dxreflector.cpp @@ -210,7 +210,7 @@ int main(int argc, const char **argv) { HRESULT hr; IFT(pReflectionResult->GetStatus(&hr)); - if(SUCCEEDED(hr)) { + if (SUCCEEDED(hr)) { IFT(pReflectionResult->GetResult(&pReflectionBlob)); IFT(pReflector->FromBlob(pReflectionBlob, &pReflectionData)); IFT(pReflector->ToString(pReflectionData, formatSettings, &pJson)); diff --git a/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp b/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp index c65c070b81..206f808f12 100644 --- a/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp +++ b/tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp @@ -100,7 +100,7 @@ FileRunCommandPart::Run(dxc::DllLoader &DllSupport, return RunDxilVer(DllSupport, Prior); } else if (0 == _stricmp(Command.c_str(), "%dxc")) { return RunDxc(DllSupport, Prior); - } else if (0 == _stricmp(Command.c_str(), "%dxreflector")) { + } else if (0 == _stricmp(Command.c_str(), "%dxreflector")) { return RunDxReflector(DllSupport, Prior); } else if (0 == _stricmp(Command.c_str(), "%dxv")) { return RunDxv(DllSupport, Prior); @@ -604,7 +604,7 @@ FileRunCommandPart::RunDxc(dxc::DllLoader &DllSupport, FileRunCommandResult FileRunCommandPart::RunDxReflector(dxc::DllLoader &DllSupport, - const FileRunCommandResult *Prior) { + const FileRunCommandResult *Prior) { // Support piping stdin from prior if needed. UNREFERENCED_PARAMETER(Prior); hlsl::options::MainArgs args; From f69f86e0ca2d277b6cb09a61c03e0b1152a9a181 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Thu, 13 Nov 2025 03:00:11 +0100 Subject: [PATCH 120/126] Fixed linux build --- tools/clang/tools/dxcreflection/dxcreflector.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 68b416d12a..7ee398243f 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -45,11 +45,13 @@ #include "dxc/DxcReflection/DxcReflectionContainer.h" #include "dxc/dxcreflect.h" +#if _WIN32 extern "C" const IID IID_IHLSLReflectionData = { 0x7016f834, 0xae85, 0x4c86, {0xa4, 0x73, 0x8c, 0x2c, 0x98, 0x1d, 0xd3, 0x70}}; +#endif using namespace llvm; using namespace clang; @@ -668,6 +670,7 @@ struct HLSLReflectionData : public IHLSLReflectionData { std::vector FunctionParameters; HLSLReflectionData() : m_refCount(1) {} + virtual ~HLSLReflectionData() = default; // TODO: This function needs another look definitely void Finalize() { @@ -799,7 +802,7 @@ struct HLSLReflectionData : public IHLSLReflectionData { if (!ppvObject) return E_POINTER; - if (riid == IID_IUnknown || riid == IID_IHLSLReflectionData) { + if (riid == IID_IHLSLReflectionData) { *ppvObject = static_cast(this); AddRef(); return S_OK; @@ -1687,6 +1690,8 @@ class DxcReflector : public IHLSLReflector, public IDxcLangExtensions3 { DXC_MICROCOM_TM_CTOR(DxcReflector) DXC_LANGEXTENSIONS_HELPER_IMPL(m_langExtensionsHelper) + virtual ~DxcReflector() = default; + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) override { return DoBasicQueryInterface Date: Thu, 13 Nov 2025 21:13:19 +0100 Subject: [PATCH 121/126] Added support for using --- include/dxc/dxcreflect.h | 6 +- .../HLSLFileCheck/dxreflector/using_test.hlsl | 130 ++++++++++++++++++ .../dxcreflection/dxcreflection_from_ast.cpp | 21 +++ .../DxcReflectionContainer.cpp | 4 +- .../DxcReflectionJson.cpp | 4 +- 5 files changed, 160 insertions(+), 5 deletions(-) create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/using_test.hlsl diff --git a/include/dxc/dxcreflect.h b/include/dxc/dxcreflect.h index 42b2728118..f421bbeebd 100644 --- a/include/dxc/dxcreflect.h +++ b/include/dxc/dxcreflect.h @@ -163,19 +163,19 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_CASE, D3D12_HLSL_NODE_TYPE_DEFAULT, + D3D12_HLSL_NODE_TYPE_USING, + // D3D12_HLSL_NODE_TYPE_IF_FIRST, // D3D12_HLSL_NODE_TYPE_ELSE_IF, // D3D12_HLSL_NODE_TYPE_ELSE, - // TODO: D3D12_HLSL_NODE_TYPE_USING, - D3D12_HLSL_NODE_TYPE_RESERVED = 1 << 7, // Highest bit; reserved as an indicator for fwd declarations D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, // Don't forget to properly update NodeTypeToString - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_DEFAULT, + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_USING, D3D12_HLSL_NODE_TYPE_INVALID }; diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/using_test.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/using_test.hlsl new file mode 100644 index 0000000000..ace6243106 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/using_test.hlsl @@ -0,0 +1,130 @@ +// RUN: %dxreflector %s | FileCheck %s + +using F32 = float; +using F64 = double; + +typedef float F32x; +typedef double F64x; + +using F32a = F32; +typedef F32 F32a2; + +struct Test { + F32 a; + F64 b; + F32x c; + F64x d; + F32a e; + F32a2 f; +}; + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "F32", +// CHECK: "NodeType": "Using", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "F64", +// CHECK: "NodeType": "Using", +// CHECK: "Type": { +// CHECK: "Name": "double" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "F32x", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "F64x", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "double" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "F32a", +// CHECK: "NodeType": "Using", +// CHECK: "Type": { +// CHECK: "Name": "F32", +// CHECK: "UnderlyingName": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "F32a2", +// CHECK: "NodeType": "Typedef", +// CHECK: "Type": { +// CHECK: "Name": "F32", +// CHECK: "UnderlyingName": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "Test", +// CHECK: "NodeType": "Struct", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "F32", +// CHECK: "UnderlyingName": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "b", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "F64", +// CHECK: "UnderlyingName": "double" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "F32x", +// CHECK: "UnderlyingName": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "d", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "F64x", +// CHECK: "UnderlyingName": "double" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "e", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "F32a", +// CHECK: "UnderlyingName": "F32" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "F32a2", +// CHECK: "UnderlyingName": "F32" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 70fe3e3eca..72c41070f1 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -2055,6 +2055,27 @@ class RecursiveReflector : public DeclVisitor { TD, D3D12_HLSL_NODE_TYPE_TYPEDEF, ParentNodeId, typeId); } + void VisitTypeAliasDecl(TypeAliasDecl *TAD) { + + if (LastError) + return; + + if (!(Features & D3D12_HLSL_REFLECTION_FEATURE_USER_TYPES)) + return; + + uint32_t typeId; + if (ReflectionError err = GenerateTypeInfo( + typeId, ASTCtx, Refl, TAD->getUnderlyingType(), DefaultRowMaj)) { + LastError = err; + return; + } + + uint32_t nodeId; + LastError = + PushNextNodeId(nodeId, Refl, SM, ASTCtx.getLangOpts(), TAD->getName(), + TAD, D3D12_HLSL_NODE_TYPE_USING, ParentNodeId, typeId); + } + void VisitFieldDecl(FieldDecl *FD) { if (LastError) diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index 47f0d4ae43..81429c9ccd 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -697,7 +697,7 @@ ReflectionData::Deserialize(const std::vector &Bytes, break; - // TODO: case D3D12_HLSL_NODE_TYPE_USING: + case D3D12_HLSL_NODE_TYPE_USING: case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: @@ -715,6 +715,7 @@ ReflectionData::Deserialize(const std::vector &Bytes, switch (node.GetNodeType()) { + case D3D12_HLSL_NODE_TYPE_USING: case D3D12_HLSL_NODE_TYPE_TYPEDEF: case D3D12_HLSL_NODE_TYPE_VARIABLE: case D3D12_HLSL_NODE_TYPE_STATIC_VARIABLE: @@ -950,6 +951,7 @@ ReflectionData::Deserialize(const std::vector &Bytes, case D3D12_HLSL_NODE_TYPE_UNION: case D3D12_HLSL_NODE_TYPE_INTERFACE: case D3D12_HLSL_NODE_TYPE_TYPEDEF: + case D3D12_HLSL_NODE_TYPE_USING: case D3D12_HLSL_NODE_TYPE_ENUM: case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 9016938068..9e284a8990 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -299,7 +299,8 @@ static const char *NodeTypeToString(D3D12_HLSL_NODE_TYPE Type) { "For", "GroupsharedVariable", "Case", - "Default"}; + "Default", + "Using"}; return arr[uint32_t(Type)]; } @@ -1256,6 +1257,7 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, [[fallthrough]]; case D3D12_HLSL_NODE_TYPE_TYPEDEF: + case D3D12_HLSL_NODE_TYPE_USING: Json.Object("Type", [&node, &Reflection, &Json, &Settings, hasSymbols, recurseType]() { From 0afdd5ebda618a4c9d8dc68d5756a71ea07d4d1a Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Thu, 13 Nov 2025 23:28:58 +0100 Subject: [PATCH 122/126] If/else chain is now properly being handled as an if root node and if first/else if/else nodes. Updated unit tests for stmts and made them easier to find issues with. Now properly handling case/default children by using get sub smt. Fixed some json serialization problems for raw_data_test. --- include/dxc/dxcreflect.h | 10 +- .../dxreflector/raw_data_test.hlsl | 1784 +++++++++-------- .../HLSLFileCheck/dxreflector/stmt_test.hlsl | 543 +++-- .../dxcreflection/dxcreflection_from_ast.cpp | 158 +- .../DxcReflectionContainer.cpp | 94 +- .../DxcReflectionJson.cpp | 72 +- 6 files changed, 1509 insertions(+), 1152 deletions(-) diff --git a/include/dxc/dxcreflect.h b/include/dxc/dxcreflect.h index f421bbeebd..e6922900aa 100644 --- a/include/dxc/dxcreflect.h +++ b/include/dxc/dxcreflect.h @@ -149,7 +149,7 @@ enum D3D12_HLSL_NODE_TYPE { // Control flow (Stmts or SwitchIfStmt), for full inspection of what variables // exist where and scopes - D3D12_HLSL_NODE_TYPE_IF, // TODO: Rename to if root + D3D12_HLSL_NODE_TYPE_IF_ROOT, D3D12_HLSL_NODE_TYPE_SCOPE, D3D12_HLSL_NODE_TYPE_DO, D3D12_HLSL_NODE_TYPE_SWITCH, @@ -165,9 +165,9 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_USING, - // D3D12_HLSL_NODE_TYPE_IF_FIRST, - // D3D12_HLSL_NODE_TYPE_ELSE_IF, - // D3D12_HLSL_NODE_TYPE_ELSE, + D3D12_HLSL_NODE_TYPE_IF_FIRST, + D3D12_HLSL_NODE_TYPE_ELSE_IF, + D3D12_HLSL_NODE_TYPE_ELSE, D3D12_HLSL_NODE_TYPE_RESERVED = 1 << 7, // Highest bit; reserved as an indicator for fwd declarations @@ -175,7 +175,7 @@ enum D3D12_HLSL_NODE_TYPE { D3D12_HLSL_NODE_TYPE_START = D3D12_HLSL_NODE_TYPE_REGISTER, // Don't forget to properly update NodeTypeToString - D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_USING, + D3D12_HLSL_NODE_TYPE_END = D3D12_HLSL_NODE_TYPE_ELSE, D3D12_HLSL_NODE_TYPE_INVALID }; diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl index f3a871f66e..b31dfecb05 100644 --- a/tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl +++ b/tools/clang/test/HLSLFileCheck/dxreflector/raw_data_test.hlsl @@ -62,881 +62,911 @@ namespace tst { } // CHECK: { -// CHECK: "Features": [ -// CHECK: "Basics", -// CHECK: "Functions", -// CHECK: "Namespaces", -// CHECK: "UserTypes", -// CHECK: "Scopes", -// CHECK: "Symbols" -// CHECK: ], -// CHECK: "Strings": [ -// CHECK: "", -// CHECK: "float", -// CHECK: "{{.*}}raw_data_test.hlsl", -// CHECK: "B", -// CHECK: "a", -// CHECK: "Test", -// CHECK: "A", -// CHECK: "C", -// CHECK: "test", -// CHECK: "b", -// CHECK: "uint", -// CHECK: "a0", -// CHECK: "a1", -// CHECK: "a2", -// CHECK: "a3", -// CHECK: "d", -// CHECK: "a4", -// CHECK: "a5", -// CHECK: "a6", -// CHECK: "a7", -// CHECK: "a8", -// CHECK: "a9", -// CHECK: "a10", -// CHECK: "int", -// CHECK: "i", -// CHECK: "a11", -// CHECK: "j", -// CHECK: "a12", -// CHECK: "bool", -// CHECK: "k", -// CHECK: "a13", -// CHECK: "tst" -// CHECK: ], -// CHECK: "StringsNonDebug": [ -// CHECK: "oxc::fancy" -// CHECK: ], -// CHECK: "Sources": [ -// CHECK: "{{.*}}raw_data_test.hlsl" -// CHECK: ], -// CHECK: "SourcesAsId": [ -// CHECK: 2 -// CHECK: ], -// CHECK: "Nodes": [ -// CHECK: { -// CHECK: "NodeId": 0, -// CHECK: "NodeType": "Namespace", -// CHECK: "NodeTypeId": 4, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": -1, -// CHECK: "ChildCount": 58, -// CHECK: "ChildStart": 1 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 1, -// CHECK: "NodeType": "Typedef", -// CHECK: "NodeTypeId": 6, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 0 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 2, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 1, -// CHECK: "ParentId": 0 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 3, -// CHECK: "NodeType": "Enum", -// CHECK: "NodeTypeId": 2, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 0, -// CHECK: "ChildCount": 2, -// CHECK: "ChildStart": 4 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 4, -// CHECK: "NodeType": "EnumValue", -// CHECK: "NodeTypeId": 3, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 3 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 5, -// CHECK: "NodeType": "EnumValue", -// CHECK: "NodeTypeId": 3, -// CHECK: "LocalId": 1, -// CHECK: "ParentId": 3 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 6, -// CHECK: "NodeType": "Interface", -// CHECK: "NodeTypeId": 10, -// CHECK: "LocalId": 2, -// CHECK: "ParentId": 0 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 7, -// CHECK: "NodeType": "Struct", -// CHECK: "NodeTypeId": 7, -// CHECK: "LocalId": 3, -// CHECK: "ParentId": 0, -// CHECK: "ChildCount": 2, -// CHECK: "ChildStart": 8 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 8, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 7 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 9, -// CHECK: "NodeType": "Function", -// CHECK: "NodeTypeId": 1, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 7 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 10, -// CHECK: "NodeType": "Register", -// CHECK: "NodeTypeId": 0, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 0, -// CHECK: "ChildCount": 1, -// CHECK: "ChildStart": 11 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 11, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 4, -// CHECK: "ParentId": 10 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 12, -// CHECK: "NodeType": "Function", -// CHECK: "NodeTypeId": 1, -// CHECK: "LocalId": 1, -// CHECK: "ParentId": 0, -// CHECK: "ChildCount": 44, -// CHECK: "ChildStart": 13, -// CHECK: "AnnotationStart": 0, -// CHECK: "AnnotationCount": 1, -// CHECK: "Annotations": [ -// CHECK: "{{\[\[oxc::fancy\]\]}}" -// CHECK: ] -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 13, -// CHECK: "NodeType": "Parameter", -// CHECK: "NodeTypeId": 11, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 12 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 14, -// CHECK: "NodeType": "Parameter", -// CHECK: "NodeTypeId": 11, -// CHECK: "LocalId": 1, -// CHECK: "ParentId": 12 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 15, -// CHECK: "NodeType": "If", -// CHECK: "NodeTypeId": 12, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 12, -// CHECK: "ChildCount": 4, -// CHECK: "ChildStart": 16 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 16, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 15 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 17, -// CHECK: "NodeType": "If", -// CHECK: "NodeTypeId": 12, -// CHECK: "LocalId": 1, -// CHECK: "ParentId": 15, -// CHECK: "ChildCount": 2, -// CHECK: "ChildStart": 18 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 18, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 17 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 19, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 17 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 20, -// CHECK: "NodeType": "Do", -// CHECK: "NodeTypeId": 14, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 12, -// CHECK: "ChildCount": 1, -// CHECK: "ChildStart": 21 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 21, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 20 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 22, -// CHECK: "NodeType": "If", -// CHECK: "NodeTypeId": 12, -// CHECK: "LocalId": 2, -// CHECK: "ParentId": 12, -// CHECK: "ChildCount": 6, -// CHECK: "ChildStart": 23 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 23, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 6, -// CHECK: "ParentId": 22 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 24, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 22 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 25, -// CHECK: "NodeType": "If", -// CHECK: "NodeTypeId": 12, -// CHECK: "LocalId": 3, -// CHECK: "ParentId": 22, -// CHECK: "ChildCount": 3, -// CHECK: "ChildStart": 26 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 26, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 6, -// CHECK: "ParentId": 25 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 27, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 25 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 28, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 25 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 29, -// CHECK: "NodeType": "Switch", -// CHECK: "NodeTypeId": 15, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 12, -// CHECK: "ChildCount": 3, -// CHECK: "ChildStart": 30 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 30, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 6, -// CHECK: "ParentId": 29 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 31, -// CHECK: "NodeType": "Default", -// CHECK: "NodeTypeId": 20, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 29, -// CHECK: "ChildCount": 1, -// CHECK: "ChildStart": 32 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 32, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 31 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 33, -// CHECK: "NodeType": "Switch", -// CHECK: "NodeTypeId": 15, -// CHECK: "LocalId": 1, -// CHECK: "ParentId": 12, -// CHECK: "ChildCount": 7, -// CHECK: "ChildStart": 34 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 34, -// CHECK: "NodeType": "Case", -// CHECK: "NodeTypeId": 19, -// CHECK: "LocalId": 1, -// CHECK: "ParentId": 33, -// CHECK: "ChildCount": 2, -// CHECK: "ChildStart": 35 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 35, -// CHECK: "NodeType": "Scope", -// CHECK: "NodeTypeId": 13, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 34, -// CHECK: "ChildCount": 1, -// CHECK: "ChildStart": 36 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 36, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 35 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 37, -// CHECK: "NodeType": "Case", -// CHECK: "NodeTypeId": 19, -// CHECK: "LocalId": 2, -// CHECK: "ParentId": 33, -// CHECK: "ChildCount": 2, -// CHECK: "ChildStart": 38 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 38, -// CHECK: "NodeType": "Scope", -// CHECK: "NodeTypeId": 13, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 37, -// CHECK: "ChildCount": 1, -// CHECK: "ChildStart": 39 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 39, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 38 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 40, -// CHECK: "NodeType": "Default", -// CHECK: "NodeTypeId": 20, -// CHECK: "LocalId": 3, -// CHECK: "ParentId": 33 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 41, -// CHECK: "NodeType": "While", -// CHECK: "NodeTypeId": 16, -// CHECK: "LocalId": 4, -// CHECK: "ParentId": 12, -// CHECK: "ChildCount": 1, -// CHECK: "ChildStart": 42 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 42, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 41 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 43, -// CHECK: "NodeType": "For", -// CHECK: "NodeTypeId": 17, -// CHECK: "LocalId": 5, -// CHECK: "ParentId": 12, -// CHECK: "ChildCount": 2, -// CHECK: "ChildStart": 44 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 44, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 7, -// CHECK: "ParentId": 43 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 45, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 43 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 46, -// CHECK: "NodeType": "For", -// CHECK: "NodeTypeId": 17, -// CHECK: "LocalId": 6, -// CHECK: "ParentId": 12, -// CHECK: "ChildCount": 3, -// CHECK: "ChildStart": 47 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 47, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 7, -// CHECK: "ParentId": 46 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 48, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 7, -// CHECK: "ParentId": 46 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 49, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 46 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 50, -// CHECK: "NodeType": "For", -// CHECK: "NodeTypeId": 17, -// CHECK: "LocalId": 7, -// CHECK: "ParentId": 12, -// CHECK: "ChildCount": 4, -// CHECK: "ChildStart": 51 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 51, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 8, -// CHECK: "ParentId": 50 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 52, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 7, -// CHECK: "ParentId": 50 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 53, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 7, -// CHECK: "ParentId": 50 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 54, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 50 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 55, -// CHECK: "NodeType": "Scope", -// CHECK: "NodeTypeId": 13, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 12, -// CHECK: "ChildCount": 1, -// CHECK: "ChildStart": 56 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 56, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 55 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 57, -// CHECK: "NodeType": "Namespace", -// CHECK: "NodeTypeId": 4, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 0, -// CHECK: "ChildCount": 1, -// CHECK: "ChildStart": 58 -// CHECK: }, -// CHECK: { -// CHECK: "NodeId": 58, -// CHECK: "NodeType": "Variable", -// CHECK: "NodeTypeId": 5, -// CHECK: "LocalId": 0, -// CHECK: "ParentId": 57 -// CHECK: } -// CHECK: ], -// CHECK: "Registers": [ -// CHECK: { -// CHECK: "RegisterId": 0, -// CHECK: "NodeId": 10, -// CHECK: "Name": "b", -// CHECK: "RegisterType": "cbuffer", -// CHECK: "BufferId": 0 -// CHECK: } -// CHECK: ], -// CHECK: "Functions": [ -// CHECK: { -// CHECK: "FunctionId": 0, -// CHECK: "NodeId": 9, -// CHECK: "Name": "test", -// CHECK: "HasDefinition": true, -// CHECK: "Params": { -// CHECK: }, -// CHECK: "ReturnType": { -// CHECK: "TypeName": "void" -// CHECK: } -// CHECK: }, -// CHECK: { -// CHECK: "FunctionId": 1, -// CHECK: "NodeId": 12, -// CHECK: "Name": "test", -// CHECK: "HasDefinition": true, -// CHECK: "Params": { -// CHECK: "a": { -// CHECK: "TypeId": 5, -// CHECK: "TypeName": "A" -// CHECK: }, -// CHECK: "b": { -// CHECK: "TypeId": 6, -// CHECK: "TypeName": "uint" -// CHECK: } -// CHECK: }, -// CHECK: "ReturnType": { -// CHECK: "TypeName": "void" -// CHECK: } -// CHECK: } -// CHECK: ], -// CHECK: "Parameters": [ -// CHECK: { -// CHECK: "ParamName": "a", -// CHECK: "TypeId": 5, -// CHECK: "TypeName": "A" -// CHECK: }, -// CHECK: { -// CHECK: "ParamName": "b", -// CHECK: "TypeId": 6, -// CHECK: "TypeName": "uint" -// CHECK: } -// CHECK: ], -// CHECK: "Enums": [ -// CHECK: { -// CHECK: "EnumId": 0, -// CHECK: "NodeId": 3, -// CHECK: "Name": "Test", -// CHECK: "EnumType": "int", -// CHECK: "Values": [ -// CHECK: { -// CHECK: "ValueId": 0, -// CHECK: "Value": 0, -// CHECK: "Symbol": { -// CHECK: "Name": "A", -// CHECK: "NameId": 6 -// CHECK: } -// CHECK: }, -// CHECK: { -// CHECK: "ValueId": 1, -// CHECK: "Value": 1, -// CHECK: "Symbol": { -// CHECK: "Name": "B", -// CHECK: "NameId": 3 -// CHECK: } -// CHECK: } -// CHECK: ] -// CHECK: } -// CHECK: ], -// CHECK: "EnumValues": [ -// CHECK: { -// CHECK: "Value": 0, -// CHECK: "Symbol": { -// CHECK: "Name": "A", -// CHECK: "NameId": 6 -// CHECK: } -// CHECK: }, -// CHECK: { -// CHECK: "Value": 1, -// CHECK: "Symbol": { -// CHECK: "Name": "B", -// CHECK: "NameId": 3 -// CHECK: } -// CHECK: } -// CHECK: ], -// CHECK: "Annotations": [ -// CHECK: { -// CHECK: "StringId": 0, -// CHECK: "Contents": "oxc::fancy", -// CHECK: "Type": "User" -// CHECK: } -// CHECK: ], -// CHECK: "Arrays": [ -// CHECK: { -// CHECK: "ArrayElem": 2, -// CHECK: "ArrayStart": 0, -// CHECK: "ArraySizes": [ -// CHECK: 2, -// CHECK: 3 -// CHECK: ] -// CHECK: }, -// CHECK: { -// CHECK: "ArrayElem": 2, -// CHECK: "ArrayStart": 2, -// CHECK: "ArraySizes": [ -// CHECK: 2, -// CHECK: 3 -// CHECK: ] -// CHECK: } -// CHECK: ], -// CHECK: "ArraySizes": [ -// CHECK: 2, -// CHECK: 3, -// CHECK: 2, -// CHECK: 3 -// CHECK: ], -// CHECK: "Members": [ -// CHECK: { -// CHECK: "Name": "a", -// CHECK: "NameId": 4, -// CHECK: "TypeId": 0, -// CHECK: "TypeName": "float" -// CHECK: }, -// CHECK: { -// CHECK: "Name": "a", -// CHECK: "NameId": 4, -// CHECK: "TypeId": 0, -// CHECK: "TypeName": "float" -// CHECK: }, -// CHECK: { -// CHECK: "Name": "a", -// CHECK: "NameId": 4, -// CHECK: "TypeId": 0, -// CHECK: "TypeName": "float" -// CHECK: } -// CHECK: ], -// CHECK: "TypeList": [ -// CHECK: { -// CHECK: "TypeId": 2, -// CHECK: "Name": "C" -// CHECK: } -// CHECK: ], -// CHECK: "Types": [ -// CHECK: { -// CHECK: "TypeId": 0, -// CHECK: "Name": "float" -// CHECK: }, -// CHECK: { -// CHECK: "TypeId": 1, -// CHECK: "Name": "float", -// CHECK: "ArraySize": [ -// CHECK: 2, -// CHECK: 3 -// CHECK: ] -// CHECK: }, -// CHECK: { -// CHECK: "TypeId": 2, -// CHECK: "Name": "C" -// CHECK: }, -// CHECK: { -// CHECK: "TypeId": 3, -// CHECK: "Name": "A", -// CHECK: "Interfaces": [ -// CHECK: { -// CHECK: "TypeId": 2, -// CHECK: "Name": "C" -// CHECK: } -// CHECK: ], -// CHECK: "Members": [ -// CHECK: { -// CHECK: "Name": "a", -// CHECK: "NameId": 4, -// CHECK: "TypeId": 0, -// CHECK: "TypeName": "float" -// CHECK: } -// CHECK: ] -// CHECK: }, -// CHECK: { -// CHECK: "TypeId": 4, -// CHECK: "Name": "A", -// CHECK: "Interfaces": [ -// CHECK: { -// CHECK: "TypeId": 2, -// CHECK: "Name": "C" -// CHECK: } -// CHECK: ], -// CHECK: "Members": [ -// CHECK: { -// CHECK: "Name": "a", -// CHECK: "NameId": 4, -// CHECK: "TypeId": 0, -// CHECK: "TypeName": "float" -// CHECK: } -// CHECK: ] -// CHECK: }, -// CHECK: { -// CHECK: "TypeId": 5, -// CHECK: "Name": "A", -// CHECK: "Interfaces": [ -// CHECK: { -// CHECK: "TypeId": 2, -// CHECK: "Name": "C" -// CHECK: } -// CHECK: ], -// CHECK: "Members": [ -// CHECK: { -// CHECK: "Name": "a", -// CHECK: "NameId": 4, -// CHECK: "TypeId": 0, -// CHECK: "TypeName": "float" -// CHECK: } -// CHECK: ] -// CHECK: }, -// CHECK: { -// CHECK: "TypeId": 6, -// CHECK: "Name": "uint" -// CHECK: }, -// CHECK: { -// CHECK: "TypeId": 7, -// CHECK: "Name": "int" -// CHECK: }, -// CHECK: { -// CHECK: "TypeId": 8, -// CHECK: "Name": "bool" -// CHECK: } -// CHECK: ], -// CHECK: "Buffers": [ -// CHECK: { -// CHECK: "BufferId": 0, -// CHECK: "NodeId": 10, -// CHECK: "Name": "b", -// CHECK: "Type": "cbuffer", -// CHECK: "Children": [ -// CHECK: { -// CHECK: "NodeId": 11, -// CHECK: "ChildId": 0, -// CHECK: "Name": "b", -// CHECK: "TypeId": 4, -// CHECK: "TypeName": "A", -// CHECK: "Interfaces": [ -// CHECK: { -// CHECK: "TypeId": 2, -// CHECK: "Name": "C" -// CHECK: } -// CHECK: ], -// CHECK: "Members": [ -// CHECK: { -// CHECK: "Name": "a", -// CHECK: "NameId": 4, -// CHECK: "TypeId": 0, -// CHECK: "TypeName": "float" -// CHECK: } -// CHECK: ] -// CHECK: } -// CHECK: ] -// CHECK: } -// CHECK: ], -// CHECK: "Statements": [ -// CHECK: { -// CHECK: "Type": "If", -// CHECK: "NodeId": 15, -// CHECK: "HasElse": true, -// CHECK: "NodesA": 1, -// CHECK: "NodesB": 3 -// CHECK: }, -// CHECK: { -// CHECK: "Type": "If", -// CHECK: "NodeId": 17, -// CHECK: "HasElse": true, -// CHECK: "NodesA": 1, -// CHECK: "NodesB": 1 -// CHECK: }, -// CHECK: { -// CHECK: "Type": "If", -// CHECK: "NodeId": 22, -// CHECK: "HasConditionVar": true, -// CHECK: "HasElse": true, -// CHECK: "NodesA": 1, -// CHECK: "NodesB": 4 -// CHECK: }, -// CHECK: { -// CHECK: "Type": "If", -// CHECK: "NodeId": 25, -// CHECK: "HasConditionVar": true, -// CHECK: "HasElse": true, -// CHECK: "NodesA": 1, -// CHECK: "NodesB": 1 -// CHECK: }, -// CHECK: { -// CHECK: "Type": "While", -// CHECK: "NodeId": 41, -// CHECK: "NodesB": 1 -// CHECK: }, -// CHECK: { -// CHECK: "Type": "For", -// CHECK: "NodeId": 43, -// CHECK: "NodesA": 1, -// CHECK: "NodesB": 1 -// CHECK: }, -// CHECK: { -// CHECK: "Type": "For", -// CHECK: "NodeId": 46, -// CHECK: "NodesA": 2, -// CHECK: "NodesB": 1 -// CHECK: }, -// CHECK: { -// CHECK: "Type": "For", -// CHECK: "NodeId": 50, -// CHECK: "HasConditionVar": true, -// CHECK: "NodesA": 2, -// CHECK: "NodesB": 1 -// CHECK: } -// CHECK: ], -// CHECK: "IfSwitchStatements": [ -// CHECK: { -// CHECK: "Type": "Switch", -// CHECK: "NodeId": 29, -// CHECK: "HasConditionVar": true, -// CHECK: "HasElseOrDefault": true -// CHECK: }, -// CHECK: { -// CHECK: "Type": "Switch", -// CHECK: "NodeId": 33, -// CHECK: "HasElseOrDefault": true -// CHECK: } -// CHECK: ], -// CHECK: "BranchStatements": [ -// CHECK: { -// CHECK: "Type": "Default", -// CHECK: "NodeId": 31, -// CHECK: "IsComplexCase": true -// CHECK: }, -// CHECK: { -// CHECK: "Type": "Case", -// CHECK: "NodeId": 34, -// CHECK: "Type": "uint", -// CHECK: "Value": 0 -// CHECK: }, -// CHECK: { -// CHECK: "Type": "Case", -// CHECK: "NodeId": 37, -// CHECK: "Type": "uint", -// CHECK: "Value": 1 -// CHECK: }, -// CHECK: { -// CHECK: "Type": "Default", -// CHECK: "NodeId": 40, -// CHECK: "IsComplexCase": true -// CHECK: } -// CHECK: ] +// CHECK: "Features": [ +// CHECK: "Basics", +// CHECK: "Functions", +// CHECK: "Namespaces", +// CHECK: "UserTypes", +// CHECK: "Scopes", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Strings": [ +// CHECK: "", +// CHECK: "float", +// CHECK: "{{.*}}raw_data_test.hlsl", +// CHECK: "B", +// CHECK: "a", +// CHECK: "Test", +// CHECK: "A", +// CHECK: "C", +// CHECK: "test", +// CHECK: "b", +// CHECK: "uint", +// CHECK: "a0", +// CHECK: "a1", +// CHECK: "a2", +// CHECK: "a3", +// CHECK: "d", +// CHECK: "a4", +// CHECK: "a5", +// CHECK: "a6", +// CHECK: "a7", +// CHECK: "a8", +// CHECK: "a9", +// CHECK: "a10", +// CHECK: "int", +// CHECK: "i", +// CHECK: "a11", +// CHECK: "j", +// CHECK: "a12", +// CHECK: "bool", +// CHECK: "k", +// CHECK: "a13", +// CHECK: "tst" +// CHECK: ], +// CHECK: "StringsNonDebug": [ +// CHECK: "oxc::fancy" +// CHECK: ], +// CHECK: "Sources": [ +// CHECK: "{{.*}}raw_data_test.hlsl" +// CHECK: ], +// CHECK: "SourcesAsId": [ +// CHECK: 2 +// CHECK: ], +// CHECK: "Nodes": [ +// CHECK: { +// CHECK: "NodeId": 0, +// CHECK: "NodeType": "Namespace", +// CHECK: "NodeTypeId": 4, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": -1, +// CHECK: "ChildCount": 60, +// CHECK: "ChildStart": 1 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 1, +// CHECK: "NodeType": "Typedef", +// CHECK: "NodeTypeId": 6, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 0 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 2, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 0 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 3, +// CHECK: "NodeType": "Enum", +// CHECK: "NodeTypeId": 2, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 0, +// CHECK: "ChildCount": 2, +// CHECK: "ChildStart": 4 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 4, +// CHECK: "NodeType": "EnumValue", +// CHECK: "NodeTypeId": 3, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 3 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 5, +// CHECK: "NodeType": "EnumValue", +// CHECK: "NodeTypeId": 3, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 3 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 6, +// CHECK: "NodeType": "Interface", +// CHECK: "NodeTypeId": 10, +// CHECK: "LocalId": 2, +// CHECK: "ParentId": 0 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 7, +// CHECK: "NodeType": "Struct", +// CHECK: "NodeTypeId": 7, +// CHECK: "LocalId": 3, +// CHECK: "ParentId": 0, +// CHECK: "ChildCount": 2, +// CHECK: "ChildStart": 8 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 8, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 7 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 9, +// CHECK: "NodeType": "Function", +// CHECK: "NodeTypeId": 1, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 7 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 10, +// CHECK: "NodeType": "Register", +// CHECK: "NodeTypeId": 0, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 0, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 11 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 11, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 4, +// CHECK: "ParentId": 10 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 12, +// CHECK: "NodeType": "Function", +// CHECK: "NodeTypeId": 1, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 0, +// CHECK: "ChildCount": 46, +// CHECK: "ChildStart": 13, +// CHECK: "AnnotationStart": 0, +// CHECK: "AnnotationCount": 1, +// CHECK: "Annotations": [ +// CHECK: "{{\[\[oxc::fancy\]\]}}" +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 13, +// CHECK: "NodeType": "Parameter", +// CHECK: "NodeTypeId": 11, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 12 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 14, +// CHECK: "NodeType": "Parameter", +// CHECK: "NodeTypeId": 11, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 12 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 15, +// CHECK: "NodeType": "IfRoot", +// CHECK: "NodeTypeId": 12, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 6, +// CHECK: "ChildStart": 16 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 16, +// CHECK: "NodeType": "IfFirst", +// CHECK: "NodeTypeId": 22, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 15, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 17 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 17, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 16 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 18, +// CHECK: "NodeType": "ElseIf", +// CHECK: "NodeTypeId": 23, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 15, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 19 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 19, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 18 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 20, +// CHECK: "NodeType": "Else", +// CHECK: "NodeTypeId": 24, +// CHECK: "LocalId": 2, +// CHECK: "ParentId": 15, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 21 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 21, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 20 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 22, +// CHECK: "NodeType": "Do", +// CHECK: "NodeTypeId": 14, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 23 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 23, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 22 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 24, +// CHECK: "NodeType": "IfRoot", +// CHECK: "NodeTypeId": 12, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 8, +// CHECK: "ChildStart": 25 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 25, +// CHECK: "NodeType": "IfFirst", +// CHECK: "NodeTypeId": 22, +// CHECK: "LocalId": 3, +// CHECK: "ParentId": 24, +// CHECK: "ChildCount": 2, +// CHECK: "ChildStart": 26 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 26, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 6, +// CHECK: "ParentId": 25 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 27, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 25 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 28, +// CHECK: "NodeType": "ElseIf", +// CHECK: "NodeTypeId": 23, +// CHECK: "LocalId": 4, +// CHECK: "ParentId": 24, +// CHECK: "ChildCount": 2, +// CHECK: "ChildStart": 29 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 29, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 6, +// CHECK: "ParentId": 28 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 30, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 28 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 31, +// CHECK: "NodeType": "Else", +// CHECK: "NodeTypeId": 24, +// CHECK: "LocalId": 5, +// CHECK: "ParentId": 24, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 32 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 32, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 31 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 33, +// CHECK: "NodeType": "Switch", +// CHECK: "NodeTypeId": 15, +// CHECK: "LocalId": 2, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 3, +// CHECK: "ChildStart": 34 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 34, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 6, +// CHECK: "ParentId": 33 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 35, +// CHECK: "NodeType": "Default", +// CHECK: "NodeTypeId": 20, +// CHECK: "LocalId": 6, +// CHECK: "ParentId": 33, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 36 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 36, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 35 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 37, +// CHECK: "NodeType": "Switch", +// CHECK: "NodeTypeId": 15, +// CHECK: "LocalId": 3, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 5, +// CHECK: "ChildStart": 38 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 38, +// CHECK: "NodeType": "Case", +// CHECK: "NodeTypeId": 19, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 37, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 39 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 39, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 38 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 40, +// CHECK: "NodeType": "Case", +// CHECK: "NodeTypeId": 19, +// CHECK: "LocalId": 8, +// CHECK: "ParentId": 37, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 41 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 41, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 40 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 42, +// CHECK: "NodeType": "Default", +// CHECK: "NodeTypeId": 20, +// CHECK: "LocalId": 9, +// CHECK: "ParentId": 37 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 43, +// CHECK: "NodeType": "While", +// CHECK: "NodeTypeId": 16, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 44 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 44, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 43 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 45, +// CHECK: "NodeType": "For", +// CHECK: "NodeTypeId": 17, +// CHECK: "LocalId": 1, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 2, +// CHECK: "ChildStart": 46 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 46, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 45 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 47, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 45 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 48, +// CHECK: "NodeType": "For", +// CHECK: "NodeTypeId": 17, +// CHECK: "LocalId": 2, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 3, +// CHECK: "ChildStart": 49 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 49, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 48 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 50, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 48 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 51, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 48 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 52, +// CHECK: "NodeType": "For", +// CHECK: "NodeTypeId": 17, +// CHECK: "LocalId": 3, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 4, +// CHECK: "ChildStart": 53 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 53, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 8, +// CHECK: "ParentId": 52 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 54, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 52 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 55, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 7, +// CHECK: "ParentId": 52 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 56, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 52 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 57, +// CHECK: "NodeType": "Scope", +// CHECK: "NodeTypeId": 13, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 12, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 58 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 58, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 57 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 59, +// CHECK: "NodeType": "Namespace", +// CHECK: "NodeTypeId": 4, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 0, +// CHECK: "ChildCount": 1, +// CHECK: "ChildStart": 60 +// CHECK: }, +// CHECK: { +// CHECK: "NodeId": 60, +// CHECK: "NodeType": "Variable", +// CHECK: "NodeTypeId": 5, +// CHECK: "LocalId": 0, +// CHECK: "ParentId": 59 +// CHECK: } +// CHECK: ], +// CHECK: "Registers": [ +// CHECK: { +// CHECK: "RegisterId": 0, +// CHECK: "NodeId": 10, +// CHECK: "Name": "b", +// CHECK: "RegisterType": "cbuffer", +// CHECK: "BufferId": 0 +// CHECK: } +// CHECK: ], +// CHECK: "Functions": [ +// CHECK: { +// CHECK: "FunctionId": 0, +// CHECK: "NodeId": 9, +// CHECK: "Name": "test", +// CHECK: "HasDefinition": true, +// CHECK: "Params": { +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "FunctionId": 1, +// CHECK: "NodeId": 12, +// CHECK: "Name": "test", +// CHECK: "HasDefinition": true, +// CHECK: "Params": { +// CHECK: "a": { +// CHECK: "TypeId": 5, +// CHECK: "TypeName": "A" +// CHECK: }, +// CHECK: "b": { +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "uint" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "void" +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Parameters": [ +// CHECK: { +// CHECK: "ParamName": "a", +// CHECK: "TypeId": 5, +// CHECK: "TypeName": "A" +// CHECK: }, +// CHECK: { +// CHECK: "ParamName": "b", +// CHECK: "TypeId": 6, +// CHECK: "TypeName": "uint" +// CHECK: } +// CHECK: ], +// CHECK: "Enums": [ +// CHECK: { +// CHECK: "EnumId": 0, +// CHECK: "NodeId": 3, +// CHECK: "Name": "Test", +// CHECK: "EnumType": "int", +// CHECK: "Values": [ +// CHECK: { +// CHECK: "ValueId": 0, +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A", +// CHECK: "NameId": 6 +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "ValueId": 1, +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B", +// CHECK: "NameId": 3 +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ], +// CHECK: "EnumValues": [ +// CHECK: { +// CHECK: "Value": 0, +// CHECK: "Symbol": { +// CHECK: "Name": "A", +// CHECK: "NameId": 6 +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Value": 1, +// CHECK: "Symbol": { +// CHECK: "Name": "B", +// CHECK: "NameId": 3 +// CHECK: } +// CHECK: } +// CHECK: ], +// CHECK: "Annotations": [ +// CHECK: { +// CHECK: "StringId": 0, +// CHECK: "Contents": "oxc::fancy", +// CHECK: "Type": "User" +// CHECK: } +// CHECK: ], +// CHECK: "Arrays": [ +// CHECK: { +// CHECK: "ArrayElem": 2, +// CHECK: "ArrayStart": 0, +// CHECK: "ArraySizes": [ +// CHECK: 2, +// CHECK: 3 +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "ArrayElem": 2, +// CHECK: "ArrayStart": 2, +// CHECK: "ArraySizes": [ +// CHECK: 2, +// CHECK: 3 +// CHECK: ] +// CHECK: } +// CHECK: ], +// CHECK: "ArraySizes": [ +// CHECK: 2, +// CHECK: 3, +// CHECK: 2, +// CHECK: 3 +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: }, +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ], +// CHECK: "TypeList": [ +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Types": [ +// CHECK: { +// CHECK: "TypeId": 0, +// CHECK: "Name": "float" +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 1, +// CHECK: "Name": "float", +// CHECK: "ArraySize": [ +// CHECK: 2, +// CHECK: 3 +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 3, +// CHECK: "Name": "A", +// CHECK: "Interfaces": [ +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 4, +// CHECK: "Name": "A", +// CHECK: "Interfaces": [ +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 5, +// CHECK: "Name": "A", +// CHECK: "Interfaces": [ +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 6, +// CHECK: "Name": "uint" +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 7, +// CHECK: "Name": "int" +// CHECK: }, +// CHECK: { +// CHECK: "TypeId": 8, +// CHECK: "Name": "bool" +// CHECK: } +// CHECK: ], +// CHECK: "Buffers": [ +// CHECK: { +// CHECK: "BufferId": 0, +// CHECK: "NodeId": 10, +// CHECK: "Name": "b", +// CHECK: "Type": "cbuffer", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeId": 11, +// CHECK: "ChildId": 0, +// CHECK: "Name": "b", +// CHECK: "TypeId": 4, +// CHECK: "TypeName": "A", +// CHECK: "Interfaces": [ +// CHECK: { +// CHECK: "TypeId": 2, +// CHECK: "Name": "C" +// CHECK: } +// CHECK: ], +// CHECK: "Members": [ +// CHECK: { +// CHECK: "Name": "a", +// CHECK: "NameId": 4, +// CHECK: "TypeId": 0, +// CHECK: "TypeName": "float" +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ], +// CHECK: "Statements": [ +// CHECK: { +// CHECK: "Type": "While", +// CHECK: "NodeId": 43, +// CHECK: "Body": 1 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "For", +// CHECK: "NodeId": 45, +// CHECK: "Init": 1, +// CHECK: "Body": 1 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "For", +// CHECK: "NodeId": 48, +// CHECK: "Init": 2, +// CHECK: "Body": 1 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "For", +// CHECK: "NodeId": 52, +// CHECK: "HasConditionVar": true, +// CHECK: "Init": 2, +// CHECK: "Body": 1 +// CHECK: } +// CHECK: ], +// CHECK: "IfSwitchStatements": [ +// CHECK: { +// CHECK: "Type": "IfRoot", +// CHECK: "NodeId": 15, +// CHECK: "HasElseOrDefault": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "IfRoot", +// CHECK: "NodeId": 24, +// CHECK: "HasElseOrDefault": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Switch", +// CHECK: "NodeId": 33, +// CHECK: "HasConditionVar": true, +// CHECK: "HasElseOrDefault": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Switch", +// CHECK: "NodeId": 37, +// CHECK: "HasElseOrDefault": true +// CHECK: } +// CHECK: ], +// CHECK: "BranchStatements": [ +// CHECK: { +// CHECK: "Type": "IfFirst", +// CHECK: "NodeId": 16, +// CHECK: "IsComplexCase": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "ElseIf", +// CHECK: "NodeId": 18, +// CHECK: "IsComplexCase": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Else", +// CHECK: "NodeId": 20, +// CHECK: "IsComplexCase": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "IfFirst", +// CHECK: "NodeId": 25, +// CHECK: "HasConditionVar": true, +// CHECK: "IsComplexCase": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "ElseIf", +// CHECK: "NodeId": 28, +// CHECK: "HasConditionVar": true, +// CHECK: "IsComplexCase": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Else", +// CHECK: "NodeId": 31, +// CHECK: "IsComplexCase": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Default", +// CHECK: "NodeId": 35, +// CHECK: "IsComplexCase": true +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Case", +// CHECK: "NodeId": 38, +// CHECK: "ValueType": "uint", +// CHECK: "Value": 0 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Case", +// CHECK: "NodeId": 40, +// CHECK: "ValueType": "uint", +// CHECK: "Value": 1 +// CHECK: }, +// CHECK: { +// CHECK: "Type": "Default", +// CHECK: "NodeId": 42, +// CHECK: "IsComplexCase": true +// CHECK: } +// CHECK: ] // CHECK: } diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl index 64af7e3ba8..94c9a090a4 100644 --- a/tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl +++ b/tools/clang/test/HLSLFileCheck/dxreflector/stmt_test.hlsl @@ -2,69 +2,101 @@ void test(uint b) { - if(uint d = b ^ 0x13) { - float c; + if(uint d0 = b ^ 0x13) { + float c0; } else { - float c; + float c1; + } + + if(uint d1 = b ^ 0x13) { + float c2; + } + + else if(uint d2 = b ^ 0x12) { + float c3; + uint e; + int f; + } + + else { + float c4; + } + + if(false) { + float c20; + } + + else if(false) { + float c21; + } + + if(true) { + float c25; + if(true) { + float c24; + } + else { + if(true) { + float c22; + } + float c23; + } } while(true) { - float c; + float c5; break; } - while(uint d = b ^ 0x13) { - float c; + while(uint d3 = b ^ 0x13) { + float c6; break; } do { - float c; + float c7; break; } while(b ^ 0x13); { - float c; + float c8; } for(uint i = 0; i < 5; ++i) { - float c; + float c9; } [unroll] - for(uint i = 0; i < 2; ++i) { - float c; + for(uint i0 = 0; i0 < 2; ++i0) { + float c10; } - for(uint i = 0, j = 5; bool k = i < 2; ++i, ++j) { - float c; + for(uint i1 = 0, j = 5; bool k = i1 < 2; ++i1, ++j) { + float c11; } - //TODO: turn into a smaller chain of ifs - if(b == 0) { - float c; + float c12; } else if(b == 1) { - float c; + float c13; } else if(b == 2) { - float c; + float c14; } else if(b == 3) { - float c; + float c15; } else { - float c; + float c16; + float c17; } - //TODO: Cases not working yet - - switch(uint d = b ^ 0x13) { + switch(uint d4 = b ^ 0x13) { case 0: - float c; + float c17; break; } @@ -82,23 +114,23 @@ void test(uint b) { switch(b) { case 0: { - float c; + float c18; break; } case 1: { - float c; + float c19; break; } case 2: { - float c; + float c20; break; } case 3: { - float c; + float c21; break; } default: { - float c; + float c22; break; } } @@ -129,41 +161,214 @@ void test(uint b) { // CHECK: }, // CHECK: "Children": [ // CHECK: { -// CHECK: "NodeType": "If", -// CHECK: "If": { -// CHECK: "Condition": { -// CHECK: "Name": "d", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "uint" -// CHECK: } +// CHECK: "NodeType": "IfRoot", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "IfFirst", +// CHECK: "Branch": { +// CHECK: "Condition": { +// CHECK: "Name": "d0", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c0", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] // CHECK: }, -// CHECK: "Body": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" +// CHECK: { +// CHECK: "NodeType": "Else", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c1", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } // CHECK: } -// CHECK: } -// CHECK: ], -// CHECK: "Else": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "IfRoot", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "IfFirst", +// CHECK: "Branch": { +// CHECK: "Condition": { +// CHECK: "Name": "d1", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } // CHECK: } -// CHECK: } -// CHECK: ] -// CHECK: } +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c2", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "ElseIf", +// CHECK: "Branch": { +// CHECK: "Condition": { +// CHECK: "Name": "d2", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: } +// CHECK: }, +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c3", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "e", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "uint" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "f", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "int" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Else", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c4", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "IfRoot", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "IfFirst", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c20", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "ElseIf", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c21", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "IfRoot", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "IfFirst", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c25", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "IfRoot", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "IfFirst", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c24", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Else", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "IfRoot", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "IfFirst", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c22", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c23", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] // CHECK: }, // CHECK: { // CHECK: "NodeType": "While", // CHECK: "While": { // CHECK: "Body": [ // CHECK: { -// CHECK: "Name": "c", +// CHECK: "Name": "c5", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "float" @@ -176,7 +381,7 @@ void test(uint b) { // CHECK: "NodeType": "While", // CHECK: "While": { // CHECK: "Condition": { -// CHECK: "Name": "d", +// CHECK: "Name": "d3", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "uint" @@ -184,7 +389,7 @@ void test(uint b) { // CHECK: }, // CHECK: "Body": [ // CHECK: { -// CHECK: "Name": "c", +// CHECK: "Name": "c6", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "float" @@ -197,7 +402,7 @@ void test(uint b) { // CHECK: "NodeType": "Do", // CHECK: "Children": [ // CHECK: { -// CHECK: "Name": "c", +// CHECK: "Name": "c7", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "float" @@ -209,7 +414,7 @@ void test(uint b) { // CHECK: "NodeType": "Scope", // CHECK: "Children": [ // CHECK: { -// CHECK: "Name": "c", +// CHECK: "Name": "c8", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "float" @@ -231,7 +436,7 @@ void test(uint b) { // CHECK: ], // CHECK: "Body": [ // CHECK: { -// CHECK: "Name": "c", +// CHECK: "Name": "c9", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "float" @@ -245,7 +450,7 @@ void test(uint b) { // CHECK: "For": { // CHECK: "Init": [ // CHECK: { -// CHECK: "Name": "i", +// CHECK: "Name": "i0", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "uint" @@ -254,7 +459,7 @@ void test(uint b) { // CHECK: ], // CHECK: "Body": [ // CHECK: { -// CHECK: "Name": "c", +// CHECK: "Name": "c10", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "float" @@ -275,7 +480,7 @@ void test(uint b) { // CHECK: }, // CHECK: "Init": [ // CHECK: { -// CHECK: "Name": "i", +// CHECK: "Name": "i1", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "uint" @@ -291,7 +496,7 @@ void test(uint b) { // CHECK: ], // CHECK: "Body": [ // CHECK: { -// CHECK: "Name": "c", +// CHECK: "Name": "c11", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "float" @@ -301,81 +506,82 @@ void test(uint b) { // CHECK: } // CHECK: }, // CHECK: { -// CHECK: "NodeType": "If", -// CHECK: "If": { -// CHECK: "Body": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" +// CHECK: "NodeType": "IfRoot", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "NodeType": "IfFirst", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c12", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } // CHECK: } -// CHECK: } -// CHECK: ], -// CHECK: "Else": [ -// CHECK: { -// CHECK: "NodeType": "If", -// CHECK: "If": { -// CHECK: "Body": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" -// CHECK: } -// CHECK: } -// CHECK: ], -// CHECK: "Else": [ -// CHECK: { -// CHECK: "NodeType": "If", -// CHECK: "If": { -// CHECK: "Body": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" -// CHECK: } -// CHECK: } -// CHECK: ], -// CHECK: "Else": [ -// CHECK: { -// CHECK: "NodeType": "If", -// CHECK: "If": { -// CHECK: "Body": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" -// CHECK: } -// CHECK: } -// CHECK: ], -// CHECK: "Else": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" -// CHECK: } -// CHECK: } -// CHECK: ] -// CHECK: } -// CHECK: } -// CHECK: ] -// CHECK: } -// CHECK: } -// CHECK: ] +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "ElseIf", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c13", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } // CHECK: } -// CHECK: } -// CHECK: ] -// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "ElseIf", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c14", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "ElseIf", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c15", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: }, +// CHECK: { +// CHECK: "NodeType": "Else", +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "c16", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: }, +// CHECK: { +// CHECK: "Name": "c17", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } +// CHECK: ] // CHECK: }, // CHECK: { // CHECK: "NodeType": "Switch", // CHECK: "Switch": { // CHECK: "Condition": { -// CHECK: "Name": "d", +// CHECK: "Name": "d4", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "uint" @@ -388,16 +594,7 @@ void test(uint b) { // CHECK: "Case": { // CHECK: "Type": "uint", // CHECK: "Value": 0 -// CHECK: }, -// CHECK: "Children": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" -// CHECK: } -// CHECK: } -// CHECK: ] +// CHECK: } // CHECK: } // CHECK: ] // CHECK: }, @@ -435,16 +632,11 @@ void test(uint b) { // CHECK: }, // CHECK: "Children": [ // CHECK: { -// CHECK: "NodeType": "Scope", -// CHECK: "Children": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" -// CHECK: } -// CHECK: } -// CHECK: ] +// CHECK: "Name": "c18", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } // CHECK: } // CHECK: ] // CHECK: }, @@ -456,16 +648,11 @@ void test(uint b) { // CHECK: }, // CHECK: "Children": [ // CHECK: { -// CHECK: "NodeType": "Scope", -// CHECK: "Children": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" -// CHECK: } -// CHECK: } -// CHECK: ] +// CHECK: "Name": "c19", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } // CHECK: } // CHECK: ] // CHECK: }, @@ -477,16 +664,11 @@ void test(uint b) { // CHECK: }, // CHECK: "Children": [ // CHECK: { -// CHECK: "NodeType": "Scope", -// CHECK: "Children": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" -// CHECK: } -// CHECK: } -// CHECK: ] +// CHECK: "Name": "c20", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } // CHECK: } // CHECK: ] // CHECK: }, @@ -498,16 +680,11 @@ void test(uint b) { // CHECK: }, // CHECK: "Children": [ // CHECK: { -// CHECK: "NodeType": "Scope", -// CHECK: "Children": [ -// CHECK: { -// CHECK: "Name": "c", -// CHECK: "NodeType": "Variable", -// CHECK: "Type": { -// CHECK: "Name": "float" -// CHECK: } -// CHECK: } -// CHECK: ] +// CHECK: "Name": "c21", +// CHECK: "NodeType": "Variable", +// CHECK: "Type": { +// CHECK: "Name": "float" +// CHECK: } // CHECK: } // CHECK: ] // CHECK: }, @@ -515,7 +692,7 @@ void test(uint b) { // CHECK: "NodeType": "Default", // CHECK: "Children": [ // CHECK: { -// CHECK: "Name": "c", +// CHECK: "Name": "c22", // CHECK: "NodeType": "Variable", // CHECK: "Type": { // CHECK: "Name": "float" diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index 72c41070f1..e20af15cd4 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -1530,12 +1530,136 @@ struct RecursiveStmtReflector : public StmtVisitor { if (LastError) return; + + uint32_t loc = uint32_t(Refl.IfSwitchStatements.size()); - LastError = GenerateStatement( - ASTCtx, Diags, SM, Refl, AutoBindingSpace, Depth + 1, Features, - ParentNodeId, DefaultRowMaj, FwdDecls, LangOpts, - D3D12_HLSL_NODE_TYPE_IF, If->getConditionVariable(), If->getElse(), - If->getThen(), If, If->getElse()); + const SourceRange &sourceRange = If->getSourceRange(); + + uint32_t nodeId; + if (ReflectionError err = + PushNextNodeId(nodeId, Refl, SM, LangOpts, "", nullptr, + D3D12_HLSL_NODE_TYPE_IF_ROOT, ParentNodeId, loc, + &sourceRange, &FwdDecls)) { + LastError = err; + return; + } + + Refl.IfSwitchStatements.push_back(ReflectionIfSwitchStmt()); + + std::vector branches; + branches.reserve(2); + branches.push_back(If); + + Stmt *child = If->getElse(); + + while (child) { + + branches.push_back(child); + + if (IfStmt *ifChild = dyn_cast(child)) + child = ifChild->getElse(); + + else + break; + } + + bool hasElse = branches.size() > 1 && !isa(branches.back()); + uint64_t counter = 0; + + for (Stmt *child : branches) { + + uint32_t loc = uint32_t(Refl.BranchStatements.size()); + Refl.BranchStatements.push_back(ReflectionBranchStmt()); + + const SourceRange &sourceRange = child->getSourceRange(); + + D3D12_HLSL_NODE_TYPE nodeType = + !counter ? D3D12_HLSL_NODE_TYPE_IF_FIRST + : (hasElse && counter + 1 == branches.size() + ? D3D12_HLSL_NODE_TYPE_ELSE + : D3D12_HLSL_NODE_TYPE_ELSE_IF); + ++counter; + + uint32_t childId; + if (ReflectionError err = + PushNextNodeId(childId, Refl, SM, LangOpts, "", nullptr, nodeType, + nodeId, loc, &sourceRange, &FwdDecls)) { + LastError = err; + return; + } + + IfStmt *branch = dyn_cast_or_null(child); + + VarDecl *cond = branch ? branch->getConditionVariable() : nullptr; + + if (cond) { + + uint32_t typeId; + if (ReflectionError err = GenerateTypeInfo( + typeId, ASTCtx, Refl, cond->getType(), DefaultRowMaj)) { + LastError = err; + return; + } + + const SourceRange &sourceRange = cond->getSourceRange(); + + uint32_t nextNodeId; + if (ReflectionError err = + PushNextNodeId(nextNodeId, Refl, SM, LangOpts, cond->getName(), + cond, D3D12_HLSL_NODE_TYPE_VARIABLE, childId, + typeId, &sourceRange, &FwdDecls)) { + LastError = err; + return; + } + } + + if (ReflectionError err = ReflectionBranchStmt::Initialize( + Refl.BranchStatements[loc], childId, cond, true, + D3D12_HLSL_ENUM_TYPE_UINT, uint64_t(-1))) { + LastError = err; + return; + } + + uint32_t parentSelf = ParentNodeId; + ParentNodeId = childId; + + Stmt *realChild = branch ? branch->getThen() : child; + auto firstIt = realChild->child_begin(); + auto it = firstIt; + + if (it != realChild->child_end()) { + + ++it; + + if (it == realChild->child_end() && isa(*firstIt)) { + + it = firstIt->child_begin(); + + for (; it != firstIt->child_end(); ++it) + if (ReflectionError err = TraverseStmt(*it)) { + LastError = err; + return; + } + } + + else { + it = firstIt; + for (; it != realChild->child_end(); ++it) + if (ReflectionError err = TraverseStmt(*it)) { + LastError = err; + return; + } + } + } + + ParentNodeId = parentSelf; + } + + if (ReflectionError err = ReflectionIfSwitchStmt::Initialize( + Refl.IfSwitchStatements[loc], nodeId, false, hasElse)) { + LastError = err; + return; + } } void VisitForStmt(ForStmt *For) { @@ -1628,18 +1752,18 @@ struct RecursiveStmtReflector : public StmtVisitor { Stmt *body = Switch->getBody(); assert(body && "SwitchStmt has no body"); - bool hasElseOrDefault = false; + bool hasDefault = false; for (Stmt *child : body->children()) { - const SwitchCase *switchCase = nullptr; + SwitchCase *switchCase = nullptr; uint64_t caseValue = uint64_t(-1); D3D12_HLSL_ENUM_TYPE valueType = D3D12_HLSL_ENUM_TYPE_INT; D3D12_HLSL_NODE_TYPE nodeType = D3D12_HLSL_NODE_TYPE_INVALID; bool isComplexCase = true; - if (const CaseStmt *caseStmt = dyn_cast(child)) { + if (CaseStmt *caseStmt = dyn_cast(child)) { switchCase = caseStmt; @@ -1658,10 +1782,10 @@ struct RecursiveStmtReflector : public StmtVisitor { nodeType = D3D12_HLSL_NODE_TYPE_CASE; - } else if (const DefaultStmt *defaultStmt = + } else if (DefaultStmt *defaultStmt = dyn_cast(child)) { switchCase = defaultStmt; - hasElseOrDefault = true; + hasDefault = true; nodeType = D3D12_HLSL_NODE_TYPE_DEFAULT; } @@ -1670,7 +1794,7 @@ struct RecursiveStmtReflector : public StmtVisitor { uint32_t loc = uint32_t(Refl.BranchStatements.size()); - const SourceRange &sourceRange = Switch->getSourceRange(); + const SourceRange &sourceRange = switchCase->getSourceRange(); uint32_t childId; if (ReflectionError err = @@ -1691,14 +1815,16 @@ struct RecursiveStmtReflector : public StmtVisitor { uint32_t parentSelf = ParentNodeId; ParentNodeId = childId; - auto firstIt = child->child_begin(); + auto realChild = switchCase->getSubStmt(); + + auto firstIt = realChild->child_begin(); auto it = firstIt; - if (it != child->child_end()) { + if (it != realChild->child_end()) { ++it; - if (it == child->child_end() && isa(*firstIt)) { + if (it == realChild->child_end() && isa(*firstIt)) { for (Stmt *childChild : firstIt->children()) if (ReflectionError err = TraverseStmt(childChild)) { LastError = err; @@ -1707,7 +1833,7 @@ struct RecursiveStmtReflector : public StmtVisitor { } else - for (Stmt *childChild : child->children()) + for (Stmt *childChild : realChild->children()) if (ReflectionError err = TraverseStmt(childChild)) { LastError = err; return; @@ -1718,7 +1844,7 @@ struct RecursiveStmtReflector : public StmtVisitor { } if (ReflectionError err = ReflectionIfSwitchStmt::Initialize( - Refl.IfSwitchStatements[loc], nodeId, cond, hasElseOrDefault)) { + Refl.IfSwitchStatements[loc], nodeId, cond, hasDefault)) { LastError = err; return; } diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp index 81429c9ccd..5e07f10421 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionContainer.cpp @@ -659,23 +659,39 @@ ReflectionData::Deserialize(const std::vector &Bytes, "Node is a default/case but doesn't belong to a switch", i); break; + case D3D12_HLSL_NODE_TYPE_IF_FIRST: + case D3D12_HLSL_NODE_TYPE_ELSE_IF: + case D3D12_HLSL_NODE_TYPE_ELSE: + + maxValue = header.BranchStatements; + + if (Nodes[node.GetParentId()].GetNodeType() != + D3D12_HLSL_NODE_TYPE_IF_ROOT) + return HLSL_REFL_ERR( + "Node is a if/else if/else but doesn't belong to an if root node", + i); + + break; + case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: - case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_IF_ROOT: case D3D12_HLSL_NODE_TYPE_FOR: case D3D12_HLSL_NODE_TYPE_WHILE: case D3D12_HLSL_NODE_TYPE_SWITCH: - maxValue = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_SWITCH - ? header.IfSwitchStatements - : (node.GetNodeType() != D3D12_HLSL_NODE_TYPE_SCOPE && - node.GetNodeType() != D3D12_HLSL_NODE_TYPE_DO - ? header.Statements - : 1); + maxValue = node.GetNodeType() != D3D12_HLSL_NODE_TYPE_SCOPE && + node.GetNodeType() != D3D12_HLSL_NODE_TYPE_DO + ? header.Statements + : 1; + + if (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_SWITCH || + node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF_ROOT) + maxValue = header.IfSwitchStatements; switch (Nodes[node.GetParentId()].GetNodeType()) { case D3D12_HLSL_NODE_TYPE_FUNCTION: - case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_IF_ROOT: case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: case D3D12_HLSL_NODE_TYPE_FOR: @@ -683,13 +699,13 @@ ReflectionData::Deserialize(const std::vector &Bytes, case D3D12_HLSL_NODE_TYPE_SWITCH: case D3D12_HLSL_NODE_TYPE_CASE: case D3D12_HLSL_NODE_TYPE_DEFAULT: - // TODO: case D3D12_HLSL_NODE_TYPE_IF_START: - // TODO: case D3D12_HLSL_NODE_TYPE_IF_ELSE: - // TODO: case D3D12_HLSL_NODE_TYPE_ELSE: + case D3D12_HLSL_NODE_TYPE_IF_FIRST: + case D3D12_HLSL_NODE_TYPE_ELSE_IF: + case D3D12_HLSL_NODE_TYPE_ELSE: break; default: - return HLSL_REFL_ERR("Node is an if/scope/do/for/while/switch but " + return HLSL_REFL_ERR("Node is an stmt but " "parent isn't of a similar " "type or function", i); @@ -727,16 +743,16 @@ ReflectionData::Deserialize(const std::vector &Bytes, i); break; - case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_IF_ROOT: case D3D12_HLSL_NODE_TYPE_SCOPE: case D3D12_HLSL_NODE_TYPE_DO: case D3D12_HLSL_NODE_TYPE_FOR: case D3D12_HLSL_NODE_TYPE_WHILE: case D3D12_HLSL_NODE_TYPE_DEFAULT: case D3D12_HLSL_NODE_TYPE_CASE: - // TODO: case D3D12_HLSL_NODE_TYPE_IF_START: - // TODO: case D3D12_HLSL_NODE_TYPE_IF_ELSE: - // TODO: case D3D12_HLSL_NODE_TYPE_ELSE: + case D3D12_HLSL_NODE_TYPE_IF_FIRST: + case D3D12_HLSL_NODE_TYPE_ELSE_IF: + case D3D12_HLSL_NODE_TYPE_ELSE: if (node.GetChildCount()) validateChildren.push_back(i); } @@ -946,7 +962,7 @@ ReflectionData::Deserialize(const std::vector &Bytes, switch (childNode.GetNodeType()) { case D3D12_HLSL_NODE_TYPE_VARIABLE: - case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_IF_ROOT: case D3D12_HLSL_NODE_TYPE_STRUCT: case D3D12_HLSL_NODE_TYPE_UNION: case D3D12_HLSL_NODE_TYPE_INTERFACE: @@ -960,9 +976,9 @@ ReflectionData::Deserialize(const std::vector &Bytes, case D3D12_HLSL_NODE_TYPE_SWITCH: case D3D12_HLSL_NODE_TYPE_DEFAULT: case D3D12_HLSL_NODE_TYPE_CASE: - // TODO: case D3D12_HLSL_NODE_TYPE_IF_START: - // TODO: case D3D12_HLSL_NODE_TYPE_IF_ELSE: - // TODO: case D3D12_HLSL_NODE_TYPE_ELSE: + case D3D12_HLSL_NODE_TYPE_IF_FIRST: + case D3D12_HLSL_NODE_TYPE_ELSE_IF: + case D3D12_HLSL_NODE_TYPE_ELSE: break; default: return HLSL_REFL_ERR( @@ -995,7 +1011,6 @@ ReflectionData::Deserialize(const std::vector &Bytes, i); switch (node.GetNodeType()) { - case D3D12_HLSL_NODE_TYPE_IF: case D3D12_HLSL_NODE_TYPE_WHILE: case D3D12_HLSL_NODE_TYPE_FOR: break; @@ -1019,7 +1034,7 @@ ReflectionData::Deserialize(const std::vector &Bytes, if (node.GetChildCount() < minParamCount) return HLSL_REFL_ERR("IfSwitchStmt didn't have required child nodes", i); - if (condVar && node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF) + if (condVar && node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF_ROOT) return HLSL_REFL_ERR("If statement can't have a conditional node in root", i); @@ -1030,13 +1045,15 @@ ReflectionData::Deserialize(const std::vector &Bytes, i); switch (node.GetNodeType()) { - case D3D12_HLSL_NODE_TYPE_IF: + case D3D12_HLSL_NODE_TYPE_IF_ROOT: case D3D12_HLSL_NODE_TYPE_SWITCH: break; default: return HLSL_REFL_ERR("IfSwitchStmt has invalid node type", i); } + bool isIf = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF_ROOT; + // Ensure there's only one default/else and the first is the IF_FIRST node. uint32_t nodeStart = Stmt.GetNodeId() + 1 + condVar; @@ -1049,24 +1066,28 @@ ReflectionData::Deserialize(const std::vector &Bytes, const ReflectionNode &child = Nodes[j]; bool isSingleNode = - child.GetNodeType() == D3D12_HLSL_NODE_TYPE_DEFAULT; // TODO: IF: ELSE + child.GetNodeType() == + (isIf ? D3D12_HLSL_NODE_TYPE_ELSE : D3D12_HLSL_NODE_TYPE_DEFAULT); if (isSingleNode) { if (hasSingleNode) return HLSL_REFL_ERR("IfSwitchStmt already has default/else", i); + if (isIf && !k) + return HLSL_REFL_ERR("IfSwitchStmt started with else", i); + hasSingleNode = true; } else { - // TODO: if (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF) - // expectedType = !k ? IF_START : ELSE_IF; - - bool invalid = child.GetNodeType() != D3D12_HLSL_NODE_TYPE_CASE; + D3D12_HLSL_NODE_TYPE expected = + !isIf ? D3D12_HLSL_NODE_TYPE_CASE + : (!k ? D3D12_HLSL_NODE_TYPE_IF_FIRST + : D3D12_HLSL_NODE_TYPE_ELSE_IF); - if (invalid) + if (child.GetNodeType() != expected) return HLSL_REFL_ERR("IfSwitchStmt has an invalid member", i); } @@ -1093,12 +1114,11 @@ ReflectionData::Deserialize(const std::vector &Bytes, if (node.GetChildCount() < minParamCount) return HLSL_REFL_ERR("IfSwitchStmt didn't have required child nodes", i); - // TODO: Else - if (condVar && (node.GetNodeType() == D3D12_HLSL_NODE_TYPE_DEFAULT || - node.GetNodeType() == D3D12_HLSL_NODE_TYPE_CASE)) - return HLSL_REFL_ERR("If statement can't have a conditional node in root", - i); + node.GetNodeType() == D3D12_HLSL_NODE_TYPE_CASE || + node.GetNodeType() == D3D12_HLSL_NODE_TYPE_ELSE)) + return HLSL_REFL_ERR( + "Default, case or else can't have a conditional node in root", i); if (condVar && Nodes[Stmt.GetNodeId() + 1].GetNodeType() != D3D12_HLSL_NODE_TYPE_VARIABLE) @@ -1109,9 +1129,9 @@ ReflectionData::Deserialize(const std::vector &Bytes, switch (node.GetNodeType()) { case D3D12_HLSL_NODE_TYPE_CASE: case D3D12_HLSL_NODE_TYPE_DEFAULT: - // TODO: case D3D12_HLSL_NODE_TYPE_IF_START: - // TODO: case D3D12_HLSL_NODE_TYPE_ELSE_IF: - // TODO: case D3D12_HLSL_NODE_TYPE_ELSE: + case D3D12_HLSL_NODE_TYPE_IF_FIRST: + case D3D12_HLSL_NODE_TYPE_ELSE_IF: + case D3D12_HLSL_NODE_TYPE_ELSE: break; default: return HLSL_REFL_ERR("IfSwitchStmt has invalid node type", i); diff --git a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp index 9e284a8990..3bb66e8391 100644 --- a/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp +++ b/tools/clang/tools/dxcreflectioncontainer/DxcReflectionJson.cpp @@ -291,7 +291,7 @@ static const char *NodeTypeToString(D3D12_HLSL_NODE_TYPE Type) { "StaticVariable", "Interface", "Parameter", - "If", + "IfRoot", "Scope", "Do", "Switch", @@ -300,7 +300,10 @@ static const char *NodeTypeToString(D3D12_HLSL_NODE_TYPE Type) { "GroupsharedVariable", "Case", "Default", - "Using"}; + "Using", + "IfFirst", + "ElseIf", + "Else"}; return arr[uint32_t(Type)]; } @@ -1087,16 +1090,11 @@ static void PrintStatement(const ReflectionData &Reflection, if (Stmt.HasConditionVar()) Json.BoolField("HasConditionVar", Stmt.HasConditionVar()); - bool isIf = node.GetNodeType() == D3D12_HLSL_NODE_TYPE_IF; - - if (isIf && Stmt.HasElse()) - Json.BoolField("HasElse", Stmt.HasElse()); - if (nodesA) - Json.UIntField("NodesA", nodesA); + Json.UIntField("Init", nodesA); if (nodesB) - Json.UIntField("NodesB", nodesB); + Json.UIntField("Body", nodesB); } static void PrintIfSwitchStatement(const ReflectionData &Reflection, @@ -1118,7 +1116,7 @@ static void PrintBranchStatement(const ReflectionData &Reflection, Json.BoolField("HasConditionVar", Stmt.HasConditionVar()); if (!Stmt.IsComplexCase()) { - Json.StringField("Type", EnumTypeToString(Stmt.GetValueType())); + Json.StringField("ValueType", EnumTypeToString(Stmt.GetValueType())); PrintValue(Json, Stmt.GetValueType(), Stmt.GetValue()); } @@ -1190,7 +1188,6 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, bool recurseType = false; const char *stmtType = nullptr; - const char *switchIfType = nullptr; switch (nodeType) { @@ -1281,13 +1278,30 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, break; - case D3D12_HLSL_NODE_TYPE_IF: - stmtType = "If"; - break; + case D3D12_HLSL_NODE_TYPE_IF_FIRST: + case D3D12_HLSL_NODE_TYPE_ELSE_IF: { + + const ReflectionBranchStmt &stmt = Reflection.BranchStatements[node.GetLocalId()]; + uint32_t start = NodeId + 1; + + if (stmt.HasConditionVar()) + Json.Object("Branch", [NodeId, &Reflection, &Json, &start, &Settings, + hasSymbols, &childrenToSkip]() { + Json.Object("Condition", [NodeId, &Reflection, &Json, &start, &Settings, + hasSymbols, &childrenToSkip]() { + if (hasSymbols) + PrintSymbol(Json, Reflection, Reflection.NodeSymbols[start], + Settings, false, true); + + start += PrintNodeRecursive(Reflection, start, Json, Settings); + ++start; + + childrenToSkip = start - NodeId - 1; + }); + }); - case D3D12_HLSL_NODE_TYPE_SWITCH: - switchIfType = "Switch"; break; + } case D3D12_HLSL_NODE_TYPE_FOR: stmtType = "For"; @@ -1298,12 +1312,10 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, break; } - // If; turns into ("Condition"), ("Body"), ("Else") // While; turns into ("Condition"), ("Body") // For; turns into ("Condition"), ("Init"), ("Body") if (stmtType) { - Json.Object(stmtType, [&node, &Reflection, &Json, &Settings, NodeId, &childrenToSkip, nodeType, hasSymbols]() { const ReflectionScopeStmt &stmt = @@ -1324,37 +1336,29 @@ uint32_t PrintNodeRecursive(const ReflectionData &Reflection, uint32_t NodeId, uint32_t end = start + stmt.GetNodeCount(); - bool isIf = nodeType == D3D12_HLSL_NODE_TYPE_IF; - const char *bodyName = isIf ? "Body" : "Init"; - if (stmt.GetNodeCount()) - PrintChildren(Reflection, Json, bodyName, start, end, Settings); - - const char *elseName = isIf ? "Else" : "Body"; + PrintChildren(Reflection, Json, "Init", start, end, Settings); - if (stmt.HasElse() || !isIf) { + start = end; + end = NodeId + 1 + node.GetChildCount(); - start = end; - end = NodeId + 1 + node.GetChildCount(); - - PrintChildren(Reflection, Json, elseName, start, end, Settings); - } + PrintChildren(Reflection, Json, "Body", start, end, Settings); childrenToSkip = node.GetChildCount(); }); } // Switch; turns into ("Condition"), ("Case": []) - // If; turns into "Ifs": [] + // If(Root); is just a container for IfFirst/ElseIf/Else (no need to handle it here) - else if (switchIfType) { + else if (nodeType == D3D12_HLSL_NODE_TYPE_SWITCH) { const ReflectionIfSwitchStmt &stmt = Reflection.IfSwitchStatements[node.GetLocalId()]; if (stmt.HasConditionVar()) - Json.Object(switchIfType, [&stmt, &Reflection, &Json, &Settings, NodeId, - &childrenToSkip, nodeType, hasSymbols]() { + Json.Object("Switch", [&stmt, &Reflection, &Json, &Settings, NodeId, + &childrenToSkip, nodeType, hasSymbols]() { uint32_t start = NodeId + 1; if (stmt.HasConditionVar()) From d03b0a5d83a41be3c66292d45647bb7a5d0831d4 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Fri, 14 Nov 2025 00:10:56 +0100 Subject: [PATCH 123/126] Fixed dxcreflect in external projects --- include/dxc/dxcreflect.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/dxc/dxcreflect.h b/include/dxc/dxcreflect.h index e6922900aa..3a6256e873 100644 --- a/include/dxc/dxcreflect.h +++ b/include/dxc/dxcreflect.h @@ -13,7 +13,7 @@ #define __DXC_REFLECT__ #ifndef _WIN32 -#include "dxc/WinAdapter.h" +#include "./WinAdapter.h" // need to disable this as it is voilated by this header #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" @@ -22,7 +22,7 @@ #endif #include "d3d12shader.h" -#include "dxc/dxcapi.h" +#include "./dxcapi.h" #ifdef _MSC_VER #define CLSID_SCOPE __declspec(selectany) extern From 9f64f3a7facfaafb12155b8b4996a8b999f28b64 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Fri, 14 Nov 2025 11:50:14 +0100 Subject: [PATCH 124/126] Added NodeId to ENUM_DESC, ENUM_VALUE, FUNCTION_DESC to allow fetching annotations and other information from nodes. Also added interpolation mode to NODE to allow struct members to have interpolation mode as well. --- include/dxc/DxcReflection/DxcReflectionContainer.h | 4 ++-- include/dxc/dxcreflect.h | 4 ++++ tools/clang/tools/dxcreflection/dxcreflector.cpp | 11 ++++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/dxc/DxcReflection/DxcReflectionContainer.h b/include/dxc/DxcReflection/DxcReflectionContainer.h index 3380d57a65..0111cba9c2 100644 --- a/include/dxc/DxcReflection/DxcReflectionContainer.h +++ b/include/dxc/DxcReflection/DxcReflectionContainer.h @@ -386,8 +386,8 @@ struct ReflectionFunctionParameter { // Mirrors D3D12_PARAMETER_DESC without // A statement is a for or a while statement. // - if HasConditionVar(): a variable in the condition -// - NodeCount children (If: children ex. else body, For: init children) -// - Rest of the body (If: else body, otherwise: normal body) +// - NodeCount children (For: init children) +// - Rest of the body (body) class ReflectionScopeStmt { uint32_t NodeId; diff --git a/include/dxc/dxcreflect.h b/include/dxc/dxcreflect.h index 3a6256e873..958caff857 100644 --- a/include/dxc/dxcreflect.h +++ b/include/dxc/dxcreflect.h @@ -95,6 +95,7 @@ struct D3D12_HLSL_FUNCTION_DESC { // signature (not including return) BOOL HasReturn; // TRUE, if function returns a value, false - it is a // subroutine + UINT NodeId; }; enum D3D12_HLSL_ENUM_TYPE { @@ -114,11 +115,13 @@ struct D3D12_HLSL_ENUM_DESC { LPCSTR Name; UINT ValueCount; D3D12_HLSL_ENUM_TYPE Type; + UINT NodeId; }; struct D3D12_HLSL_ENUM_VALUE { LPCSTR Name; INT64 Value; + UINT NodeId; }; struct D3D12_HLSL_ANNOTATION { @@ -189,6 +192,7 @@ struct D3D12_HLSL_NODE { UINT AnnotationCount; UINT FwdBckDeclareNode; // If UINT_MAX has no forward / backward declare BOOL IsFwdDeclare; + D3D_INTERPOLATION_MODE InterpolationMode; }; struct D3D12_HLSL_NODE_SYMBOL { diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 7ee398243f..9d011e3536 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -908,7 +908,7 @@ struct HLSLReflectionData : public IHLSLReflectionData { : ""; *pDesc = D3D12_HLSL_ENUM_DESC{ - name, uint32_t(Data.Nodes[enm.NodeId].GetChildCount()), enm.Type}; + name, uint32_t(Data.Nodes[enm.NodeId].GetChildCount()), enm.Type, enm.NodeId}; return S_OK; } @@ -936,8 +936,8 @@ struct HLSLReflectionData : public IHLSLReflectionData { const ReflectionNode &node = Data.Nodes[enm.NodeId + 1 + ValueIndex]; - *pValueDesc = - D3D12_HLSL_ENUM_VALUE{name, Data.EnumValues[node.GetLocalId()].Value}; + *pValueDesc = D3D12_HLSL_ENUM_VALUE{ + name, Data.EnumValues[node.GetLocalId()].Value, enm.NodeId}; return S_OK; } @@ -985,7 +985,7 @@ struct HLSLReflectionData : public IHLSLReflectionData { : ""; *pDesc = D3D12_HLSL_FUNCTION_DESC{name, func.GetNumParameters(), - func.HasReturn()}; + func.HasReturn(), func.GetNodeId()}; return S_OK; } @@ -1034,7 +1034,8 @@ struct HLSLReflectionData : public IHLSLReflectionData { node.GetAnnotationCount(), node.IsFwdBckDefined() ? node.GetFwdBck() : uint32_t(-1), - node.IsFwdDeclare()}; + node.IsFwdDeclare(), + node.GetInterpolationMode()}; return S_OK; } From 5652f2a1f81fdf96c23821c7e5f00c7596fddf93 Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Sun, 16 Nov 2025 21:25:00 +0100 Subject: [PATCH 125/126] Fixed certain types not being exposed to reflection such as enums, functions, interfaces, unions and structs --- .../tools/dxcreflection/dxcreflector.cpp | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/tools/clang/tools/dxcreflection/dxcreflector.cpp b/tools/clang/tools/dxcreflection/dxcreflector.cpp index 9d011e3536..6cabaf3dc0 100644 --- a/tools/clang/tools/dxcreflection/dxcreflector.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflector.cpp @@ -709,42 +709,39 @@ struct HLSLReflectionData : public IHLSLReflectionData { continue; } - if (!node.IsFwdDeclare() && node.IsFwdBckDefined()) { + FwdDeclType type = FwdDeclType::COUNT; - FwdDeclType type = FwdDeclType::COUNT; + switch (node.GetNodeType()) { - switch (node.GetNodeType()) { + case D3D12_HLSL_NODE_TYPE_STRUCT: + type = FwdDeclType::STRUCT; + break; - case D3D12_HLSL_NODE_TYPE_STRUCT: - type = FwdDeclType::STRUCT; - break; + case D3D12_HLSL_NODE_TYPE_UNION: + type = FwdDeclType::UNION; + break; - case D3D12_HLSL_NODE_TYPE_UNION: - type = FwdDeclType::UNION; - break; + case D3D12_HLSL_NODE_TYPE_INTERFACE: + type = FwdDeclType::INTERFACE; + break; - case D3D12_HLSL_NODE_TYPE_INTERFACE: - type = FwdDeclType::INTERFACE; - break; + case D3D12_HLSL_NODE_TYPE_FUNCTION: + type = FwdDeclType::FUNCTION; + break; - case D3D12_HLSL_NODE_TYPE_FUNCTION: - type = FwdDeclType::FUNCTION; - break; - - case D3D12_HLSL_NODE_TYPE_ENUM: - type = FwdDeclType::ENUM; - break; - } + case D3D12_HLSL_NODE_TYPE_ENUM: + type = FwdDeclType::ENUM; + break; + } - if (type != FwdDeclType::COUNT) { + if (type != FwdDeclType::COUNT) { - uint32_t typeId = node.GetLocalId(); + uint32_t typeId = node.GetLocalId(); - NonFwdIds[int(type)].push_back(typeId); + NonFwdIds[int(type)].push_back(typeId); - if (hasSymbols) - NameToNonFwdIds[int(type)][Data.NodeIdToFullyResolved[i]] = typeId; - } + if (hasSymbols) + NameToNonFwdIds[int(type)][Data.NodeIdToFullyResolved[i]] = typeId; } for (uint32_t j = 0; j < node.GetChildCount(); ++j) { From c00fc3106fb5bafa78b38198a25271f4d7bd028c Mon Sep 17 00:00:00 2001 From: Nielsbishere Date: Mon, 17 Nov 2025 17:48:18 +0100 Subject: [PATCH 126/126] Fixed -reflect-function when a definition is found but the fwd declare is missing --- .../dxreflector/fwd_declare_test2.hlsl | 55 ++++++++++++++ .../dxcreflection/dxcreflection_from_ast.cpp | 73 +++++++++++-------- 2 files changed, 97 insertions(+), 31 deletions(-) create mode 100644 tools/clang/test/HLSLFileCheck/dxreflector/fwd_declare_test2.hlsl diff --git a/tools/clang/test/HLSLFileCheck/dxreflector/fwd_declare_test2.hlsl b/tools/clang/test/HLSLFileCheck/dxreflector/fwd_declare_test2.hlsl new file mode 100644 index 0000000000..ed1d9c8548 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/dxreflector/fwd_declare_test2.hlsl @@ -0,0 +1,55 @@ +// RUN: %dxreflector -reflect-functions %s | FileCheck %s + +struct PSInput { + float4 color : COLOR; +}; + +struct Test; + +struct A { + float a; + float t(Test t); +}; + +struct Test { + float a; +}; + +float A::t(Test t) { + return 2; +} + +[[oxc::stage("pixel")]] +float4 PSMain(PSInput input) : SV_TARGET +{ + A a; + Test t; + return input.color * a.t(t); +} + +// CHECK: { +// CHECK: "Features": [ +// CHECK: "Functions", +// CHECK: "Symbols" +// CHECK: ], +// CHECK: "Children": [ +// CHECK: { +// CHECK: "Name": "PSMain", +// CHECK: "NodeType": "Function", +// CHECK: "Semantic": "SV_TARGET", +// CHECK: "Annotations": [ +// CHECK: {{"\[\[oxc::stage\(\\\"pixel\\\"\)\]\]"}} +// CHECK: ], +// CHECK: "Function": { +// CHECK: "Params": { +// CHECK: "input": { +// CHECK: "TypeName": "PSInput" +// CHECK: } +// CHECK: }, +// CHECK: "ReturnType": { +// CHECK: "TypeName": "float4" +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: ] +// CHECK: } \ No newline at end of file diff --git a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp index e20af15cd4..23c00a874d 100644 --- a/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp +++ b/tools/clang/tools/dxcreflection/dxcreflection_from_ast.cpp @@ -97,6 +97,48 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, if (LocalId >= (1u << 24)) return HLSL_REFL_ERR("LocalId overflow"); + bool isFwdDeclare = false; + bool canHaveFwdDeclare = false; + const Decl *fwdDeclare = nullptr; + + if (DeclSelf) { + + if (const FunctionDecl *func = dyn_cast(DeclSelf)) { + isFwdDeclare = !func->doesThisDeclarationHaveABody(); + fwdDeclare = func->getCanonicalDecl(); + canHaveFwdDeclare = true; + } + + else if (const EnumDecl *enm = dyn_cast(DeclSelf)) { + isFwdDeclare = !enm->isCompleteDefinition(); + fwdDeclare = enm->getCanonicalDecl(); + canHaveFwdDeclare = true; + } + + else if (const RecordDecl *rec = dyn_cast(DeclSelf)) { + + isFwdDeclare = !rec->isThisDeclarationADefinition(); + fwdDeclare = rec->getCanonicalDecl(); + canHaveFwdDeclare = true; + + if (isFwdDeclare && rec->isImplicit()) { // Inner ghost node + NodeId = uint32_t(-1); + return ReflectionErrorSuccess; + } + } + } + + //There is a forward declare, but we haven't seen it before. + //This happens for example if we have a fwd func declare in a struct, but define it in global namespace. + //(only) -reflect-function will hide this struct from us, but will still find a function in the global scope. + //This fixes that problem. + + if (!isFwdDeclare && fwdDeclare && fwdDeclare != DeclSelf && + FwdDecls->find(fwdDeclare) == FwdDecls->end()) { + NodeId = uint32_t(-1); + return ReflectionErrorSuccess; + } + uint32_t nodeId = Refl.Nodes.size(); uint16_t annotationStart = uint16_t(Refl.Annotations.size()); @@ -179,37 +221,6 @@ PushNextNodeId(uint32_t &NodeId, ReflectionData &Refl, const SourceManager &SM, D3D_INTERPOLATION_MODE interpolationMode = GetInterpolationMode(DeclSelf); - bool isFwdDeclare = false; - bool canHaveFwdDeclare = false; - const Decl *fwdDeclare = nullptr; - - if (DeclSelf) { - - if (const FunctionDecl *func = dyn_cast(DeclSelf)) { - isFwdDeclare = !func->doesThisDeclarationHaveABody(); - fwdDeclare = func->getCanonicalDecl(); - canHaveFwdDeclare = true; - } - - else if (const EnumDecl *enm = dyn_cast(DeclSelf)) { - isFwdDeclare = !enm->isCompleteDefinition(); - fwdDeclare = enm->getCanonicalDecl(); - canHaveFwdDeclare = true; - } - - else if (const RecordDecl *rec = dyn_cast(DeclSelf)) { - - isFwdDeclare = !rec->isThisDeclarationADefinition(); - fwdDeclare = rec->getCanonicalDecl(); - canHaveFwdDeclare = true; - - if (isFwdDeclare && rec->isImplicit()) { // Inner ghost node - NodeId = uint32_t(-1); - return ReflectionErrorSuccess; - } - } - } - uint32_t currId = uint32_t(Refl.Nodes.size()); if (canHaveFwdDeclare) {