Author: Finn Plummer Date: 2026-08-19T10:13:48-07:00 New Revision: b48b6961dc64d967f4912e1a559cae96ac5feb27
URL: https://github.com/llvm/llvm-project/commit/b48b6961dc64d967f4912e1a559cae96ac5feb27 DIFF: https://github.com/llvm/llvm-project/commit/b48b6961dc64d967f4912e1a559cae96ac5feb27.diff LOG: Reland "[HLSL] Generate semantic signature metadata (#212892)" (#216805) This pr relands #212892. It was reverted because it used a helper function from `LLVMBinaryFormat` but didn't not update the `clangCodegen` CMake build dep. This pr addresses this by moving the helper function to a common place of `LLVMHLSLFrontend` which is already included by `clangCodegen` and which already depends on `LLVMBinaryFormat`. This is preferred as it is a more natural place for this helper. Added: Modified: clang/lib/CodeGen/CGHLSLRuntime.cpp clang/lib/CodeGen/CGHLSLRuntime.h clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl clang/test/CodeGenHLSL/semantics/semantic.input.hlsl clang/test/CodeGenHLSL/semantics/semantic.output.hlsl llvm/include/llvm/Frontend/HLSL/HLSLResource.h llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h llvm/lib/Analysis/DXILResource.cpp llvm/lib/Frontend/HLSL/HLSLResource.cpp llvm/lib/Frontend/HLSL/SemanticSignatures.cpp llvm/unittests/Frontend/HLSLSemanticSignatureMetadataTest.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 814894ea14da7..05f755edde64b 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -31,10 +31,12 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetOptions.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Enum.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Frontend/HLSL/HLSLResource.h" #include "llvm/Frontend/HLSL/RootSignatureMetadata.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" @@ -102,6 +104,33 @@ void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer, RootSignatureValMD->addOperand(MDVals); } +MDNode *buildSemanticSignatureMD( + ArrayRef<llvm::hlsl::SemanticSignatureElement> Elements, LLVMContext &Ctx) { + if (Elements.empty()) + return nullptr; + + SmallVector<Metadata *> ElementMD; + for (const llvm::hlsl::SemanticSignatureElement &Element : Elements) + ElementMD.push_back(Element.toMetadata(Ctx)); + return MDNode::get(Ctx, ElementMD); +} + +void addSemanticSignatureMD( + ArrayRef<llvm::hlsl::SemanticSignatureElement> InputElements, + ArrayRef<llvm::hlsl::SemanticSignatureElement> OutputElements, + llvm::Function *Fn, llvm::Module &M) { + if (InputElements.empty() && OutputElements.empty()) + return; + + LLVMContext &Ctx = M.getContext(); + MDNode *InputSignature = buildSemanticSignatureMD(InputElements, Ctx); + MDNode *OutputSignature = buildSemanticSignatureMD(OutputElements, Ctx); + MDNode *MDVals = MDNode::get( + Ctx, {ValueAsMetadata::get(Fn), InputSignature, OutputSignature}); + + M.getOrInsertNamedMetadata("dx.semantic.signatures")->addOperand(MDVals); +} + static void copyGlobalResource(CodeGenFunction &CGF, const VarDecl *ResourceVD, AggValueSlot &DestSlot) { GlobalVariable *ResGV = @@ -1246,13 +1275,51 @@ static SemanticShape getSemanticShape(ASTContext &Ctx, QualType Ty) { return Shape; } +static llvm::dxil::ElementType getSignatureComponentType(CodeGenModule &CGM, + QualType Ty) { + if (const auto *VT = Ty->getAs<clang::VectorType>()) + Ty = VT->getElementType(); + else if (const auto *MT = Ty->getAs<clang::ConstantMatrixType>()) + Ty = MT->getElementType(); + + llvm::Type *IRTy = CGM.getTypes().ConvertTypeForMem(Ty); + bool IsSigned = Ty->isSignedIntegerOrEnumerationType(); + return llvm::hlsl::getDXILElementType(IRTy, IsSigned); +} + +static llvm::hlsl::SemanticSignatureElement createSemanticSignatureElement( + CodeGenModule &CGM, uint32_t SigId, HLSLAppliedSemanticAttr *Semantic, + std::optional<unsigned> Index, const SemanticShape &Shape) { + StringRef Name = Semantic->getAttrName()->getName(); + + // One semantic index per row, starting from the declared index. + SmallVector<uint32_t> SemanticIndices; + uint32_t FirstSemanticIndex = Index.value_or(0); + for (uint32_t I = 0, E = Shape.getNumRows(); I < E; ++I) + SemanticIndices.push_back(FirstSemanticIndex + I); + + // The remaining members keep their default value and will be filled at a + // later stage, either during packing or analysis of usage + // + // FIXME #189762: Element.InterpMode is to be set + return llvm::hlsl::SemanticSignatureElement( + SigId, Name, getSignatureComponentType(CGM, Shape.RowType), + llvm::hlsl::getSemanticKind(Name), SemanticIndices, + static_cast<uint8_t>(Shape.Cols)); +} + llvm::Value *CGHLSLRuntime::emitDXILUserSemanticLoad( llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, - HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) { + HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index, + SemanticSignatures &Signature) { StringRef Name = Semantic->getAttrName()->getName(); SemanticShape Shape = getSemanticShape(CGM.getContext(), getSemanticLeafType(Decl)); + uint32_t SigId = Signature.size(); + Signature.push_back( + createSemanticSignatureElement(CGM, SigId, Semantic, Index, Shape)); + llvm::Type *RowTy = CGM.getTypes().ConvertTypeForMem(Shape.RowType); llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration( @@ -1264,8 +1331,6 @@ llvm::Value *CGHLSLRuntime::emitDXILUserSemanticLoad( OB.emplace_back("convergencectrl", bundleArgs); } - unsigned SigId = DXILInputSemanticIndex++; - llvm::Type *LeafTy = CGM.getTypes().ConvertType(Shape.RowType); llvm::Value *Result = llvm::PoisonValue::get(Type); @@ -1299,9 +1364,15 @@ void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, - std::optional<unsigned> Index) { + std::optional<unsigned> Index, + SemanticSignatures &Signature) { SemanticShape Shape = getSemanticShape(CGM.getContext(), getSemanticLeafType(Decl)); + + uint32_t SigId = Signature.size(); + Signature.push_back( + createSemanticSignatureElement(CGM, SigId, Semantic, Index, Shape)); + llvm::Type *RowTy = CGM.getTypes().ConvertTypeForMem(Shape.RowType); llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration( @@ -1314,8 +1385,6 @@ void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B, OB.emplace_back("convergencectrl", bundleArgs); } - unsigned SigId = DXILOutputSemanticIndex++; - const unsigned NumRows = Shape.getNumRows(); for (unsigned Row = 0; Row < NumRows; ++Row) { SmallVector<unsigned> Indices = Shape.getArrayIndicesForRow(Row); @@ -1340,12 +1409,12 @@ void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *CGHLSLRuntime::emitUserSemanticLoad( IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, - std::optional<unsigned> Index) { + std::optional<unsigned> Index, SemanticSignatures &Signature) { if (CGM.getTarget().getTriple().isSPIRV()) return emitSPIRVUserSemanticLoad(B, FD, Type, Decl, Semantic, Index); if (CGM.getTarget().getTriple().isDXIL()) - return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index); + return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index, Signature); llvm_unreachable("Unsupported target for user-semantic load."); } @@ -1353,12 +1422,14 @@ llvm::Value *CGHLSLRuntime::emitUserSemanticLoad( void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, - std::optional<unsigned> Index) { + std::optional<unsigned> Index, + SemanticSignatures &Signature) { if (CGM.getTarget().getTriple().isSPIRV()) return emitSPIRVUserSemanticStore(B, Source, Decl, Semantic, Index); if (CGM.getTarget().getTriple().isDXIL()) - return emitDXILUserSemanticStore(B, Source, Decl, Semantic, Index); + return emitDXILUserSemanticStore(B, Source, Decl, Semantic, Index, + Signature); llvm_unreachable("Unsupported target for user-semantic load."); } @@ -1366,7 +1437,7 @@ void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source, llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad( IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, - std::optional<unsigned> Index) { + std::optional<unsigned> Index, SemanticSignatures &Signature) { std::string SemanticName = Semantic->getAttrName()->getName().upper(); if (SemanticName == "SV_GROUPINDEX") { @@ -1413,11 +1484,13 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad( Semantic->getAttrName()->getName(), /* BuiltIn::FragCoord */ 15); if (CGM.getTarget().getTriple().isDXIL()) - return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index); + return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index, + Signature); } if (ST == Triple::EnvironmentType::Vertex) { - return emitUserSemanticLoad(B, FD, Type, Decl, Semantic, Index); + return emitUserSemanticLoad(B, FD, Type, Decl, Semantic, Index, + Signature); } } @@ -1428,7 +1501,8 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad( Semantic->getAttrName()->getName(), /* BuiltIn::VertexIndex */ 42); else - return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index); + return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index, + Signature); } } @@ -1453,12 +1527,13 @@ static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M, void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, - std::optional<unsigned> Index) { + std::optional<unsigned> Index, + SemanticSignatures &Signature) { std::string SemanticName = Semantic->getAttrName()->getName().upper(); if (SemanticName == "SV_POSITION") { if (CGM.getTarget().getTriple().isDXIL()) { - emitDXILUserSemanticStore(B, Source, Decl, Semantic, Index); + emitDXILUserSemanticStore(B, Source, Decl, Semantic, Index, Signature); return; } @@ -1471,7 +1546,7 @@ void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source, } if (SemanticName == "SV_TARGET") { - emitUserSemanticStore(B, Source, Decl, Semantic, Index); + emitUserSemanticStore(B, Source, Decl, Semantic, Index, Signature); return; } @@ -1481,22 +1556,27 @@ void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source, llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad( IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, - const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) { + const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, + SemanticSignatures &Signature) { std::optional<unsigned> Index = Semantic->getSemanticIndex(); if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_")) - return emitSystemSemanticLoad(B, FD, Type, Decl, Semantic, Index); - return emitUserSemanticLoad(B, FD, Type, Decl, Semantic, Index); + return emitSystemSemanticLoad(B, FD, Type, Decl, Semantic, Index, + Signature); + return emitUserSemanticLoad(B, FD, Type, Decl, Semantic, Index, Signature); } -void CGHLSLRuntime::handleScalarSemanticStore( - IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, - const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) { +void CGHLSLRuntime::handleScalarSemanticStore(IRBuilder<> &B, + const FunctionDecl *FD, + llvm::Value *Source, + const clang::DeclaratorDecl *Decl, + HLSLAppliedSemanticAttr *Semantic, + SemanticSignatures &Signature) { std::optional<unsigned> Index = Semantic->getSemanticIndex(); if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_")) - emitSystemSemanticStore(B, Source, Decl, Semantic, Index); + emitSystemSemanticStore(B, Source, Decl, Semantic, Index, Signature); else - emitUserSemanticStore(B, Source, Decl, Semantic, Index); + emitUserSemanticStore(B, Source, Decl, Semantic, Index, Signature); } std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>> @@ -1504,7 +1584,8 @@ CGHLSLRuntime::handleStructSemanticLoad( IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin, - specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) { + specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd, + SemanticSignatures &Signature) { const llvm::StructType *ST = cast<StructType>(Type); const clang::RecordDecl *RD = Decl->getType()->getAsRecordDecl(); @@ -1513,8 +1594,9 @@ CGHLSLRuntime::handleStructSemanticLoad( llvm::Value *Aggregate = llvm::PoisonValue::get(Type); auto FieldDecl = RD->field_begin(); for (unsigned I = 0; I < ST->getNumElements(); ++I) { - auto [ChildValue, NextAttr] = handleSemanticLoad( - B, FD, ST->getElementType(I), *FieldDecl, AttrBegin, AttrEnd); + auto [ChildValue, NextAttr] = + handleSemanticLoad(B, FD, ST->getElementType(I), *FieldDecl, AttrBegin, + AttrEnd, Signature); AttrBegin = NextAttr; assert(ChildValue); Aggregate = B.CreateInsertValue(Aggregate, ChildValue, I); @@ -1529,7 +1611,8 @@ CGHLSLRuntime::handleStructSemanticStore( IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin, - specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) { + specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd, + SemanticSignatures &Signature) { const llvm::StructType *ST = cast<StructType>(Source->getType()); @@ -1545,8 +1628,8 @@ CGHLSLRuntime::handleStructSemanticStore( auto FieldDecl = RD->field_begin(); for (unsigned I = 0; I < ST->getNumElements(); ++I, ++FieldDecl) { llvm::Value *Extract = B.CreateExtractValue(Source, I); - AttrBegin = - handleSemanticStore(B, FD, Extract, *FieldDecl, AttrBegin, AttrEnd); + AttrBegin = handleSemanticStore(B, FD, Extract, *FieldDecl, AttrBegin, + AttrEnd, Signature); } return AttrBegin; @@ -1557,15 +1640,17 @@ CGHLSLRuntime::handleSemanticLoad( IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin, - specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) { + specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd, + SemanticSignatures &Signature) { assert(AttrBegin != AttrEnd); if (Type->isStructTy()) - return handleStructSemanticLoad(B, FD, Type, Decl, AttrBegin, AttrEnd); + return handleStructSemanticLoad(B, FD, Type, Decl, AttrBegin, AttrEnd, + Signature); HLSLAppliedSemanticAttr *Attr = *AttrBegin; ++AttrBegin; - return std::make_pair(handleScalarSemanticLoad(B, FD, Type, Decl, Attr), - AttrBegin); + return std::make_pair( + handleScalarSemanticLoad(B, FD, Type, Decl, Attr, Signature), AttrBegin); } specific_attr_iterator<HLSLAppliedSemanticAttr> @@ -1573,21 +1658,23 @@ CGHLSLRuntime::handleSemanticStore( IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin, - specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) { + specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd, + SemanticSignatures &Signature) { assert(AttrBegin != AttrEnd); if (Source->getType()->isStructTy()) - return handleStructSemanticStore(B, FD, Source, Decl, AttrBegin, AttrEnd); + return handleStructSemanticStore(B, FD, Source, Decl, AttrBegin, AttrEnd, + Signature); HLSLAppliedSemanticAttr *Attr = *AttrBegin; ++AttrBegin; - handleScalarSemanticStore(B, FD, Source, Decl, Attr); + handleScalarSemanticStore(B, FD, Source, Decl, Attr, Signature); return AttrBegin; } void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn) { - DXILInputSemanticIndex = 0; - DXILOutputSemanticIndex = 0; + SmallVector<llvm::hlsl::SemanticSignatureElement> InputSignature; + SmallVector<llvm::hlsl::SemanticSignatureElement> OutputSignature; llvm::Module &M = CGM.getModule(); llvm::LLVMContext &Ctx = M.getContext(); @@ -1651,8 +1738,8 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, auto AttrBegin = PD->specific_attr_begin<HLSLAppliedSemanticAttr>(); auto AttrEnd = PD->specific_attr_end<HLSLAppliedSemanticAttr>(); - auto Result = - handleSemanticLoad(B, FD, ParamType, PD, AttrBegin, AttrEnd); + auto Result = handleSemanticLoad(B, FD, ParamType, PD, AttrBegin, AttrEnd, + InputSignature); SemanticValue = Result.first; if (!SemanticValue) return; @@ -1685,7 +1772,8 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, auto AttrBegin = FD->specific_attr_begin<HLSLAppliedSemanticAttr>(); auto AttrEnd = FD->specific_attr_end<HLSLAppliedSemanticAttr>(); - handleSemanticStore(B, FD, SourceValue, FD, AttrBegin, AttrEnd); + handleSemanticStore(B, FD, SourceValue, FD, AttrBegin, AttrEnd, + OutputSignature); } B.CreateRetVoid(); @@ -1698,6 +1786,8 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, EntryFn, M); } } + + addSemanticSignatureMD(InputSignature, OutputSignature, EntryFn, M); } static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M, diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 0b282f19cfcbc..2f251505cfa3e 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -24,6 +24,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Frontend/HLSL/HLSLResource.h" +#include "llvm/Frontend/HLSL/SemanticSignatures.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsDirectX.h" @@ -216,54 +217,65 @@ class CGHLSLRuntime { //===----------------------------------------------------------------------===// protected: + using SemanticSignatures = + llvm::SmallVectorImpl<llvm::hlsl::SemanticSignatureElement>; + CodeGenModule &CGM; llvm::Value *emitSystemSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, - std::optional<unsigned> Index); + std::optional<unsigned> Index, + SemanticSignatures &Signature); void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, - std::optional<unsigned> Index); + std::optional<unsigned> Index, + SemanticSignatures &Signature); llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, - HLSLAppliedSemanticAttr *Semantic); + HLSLAppliedSemanticAttr *Semantic, + SemanticSignatures &Signature); void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, - HLSLAppliedSemanticAttr *Semantic); + HLSLAppliedSemanticAttr *Semantic, + SemanticSignatures &Signature); std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>> handleStructSemanticLoad( llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator<HLSLAppliedSemanticAttr> begin, - specific_attr_iterator<HLSLAppliedSemanticAttr> end); + specific_attr_iterator<HLSLAppliedSemanticAttr> end, + SemanticSignatures &Signature); specific_attr_iterator<HLSLAppliedSemanticAttr> handleStructSemanticStore( llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin, - specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd); + specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd, + SemanticSignatures &Signature); std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>> handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator<HLSLAppliedSemanticAttr> begin, - specific_attr_iterator<HLSLAppliedSemanticAttr> end); + specific_attr_iterator<HLSLAppliedSemanticAttr> end, + SemanticSignatures &Signature); specific_attr_iterator<HLSLAppliedSemanticAttr> handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin, - specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd); + specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd, + SemanticSignatures &Signature); public: CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {} @@ -337,12 +349,14 @@ class CGHLSLRuntime { llvm::Value *emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, - std::optional<unsigned> Index); + std::optional<unsigned> Index, + SemanticSignatures &Signature); llvm::Value *emitUserSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, - std::optional<unsigned> Index); + std::optional<unsigned> Index, + SemanticSignatures &Signature); void emitSPIRVUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, @@ -351,11 +365,13 @@ class CGHLSLRuntime { void emitDXILUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, - std::optional<unsigned> Index); + std::optional<unsigned> Index, + SemanticSignatures &Signature); void emitUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, - std::optional<unsigned> Index); + std::optional<unsigned> Index, + SemanticSignatures &Signature); bool initializeGlobalResourceArray(CodeGenFunction &CGF, const VarDecl *ArrayDecl, @@ -366,12 +382,6 @@ class CGHLSLRuntime { llvm::DenseMap<const clang::RecordType *, llvm::StructType *> LayoutTypes; unsigned SPIRVLastAssignedInputSemanticLocation = 0; unsigned SPIRVLastAssignedOutputSemanticLocation = 0; - - // FIXME: #57928, storing these here and reseting them in the entry is not - // very nice and is a temporary until we accumulate the signatures as part of - // the mentioned issue. - unsigned DXILInputSemanticIndex = 0; - unsigned DXILOutputSemanticIndex = 0; }; } // namespace CodeGen diff --git a/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl index 8c8fe6443183e..5427a569e5eee 100644 --- a/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl +++ b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl @@ -34,6 +34,11 @@ S0 main1(float4 input : A) : B { return output; } +// CHECK-DXIL: !dx.semantic.signatures = !{![[#ENTRY_SIG:]]} +// CHECK-DXIL: ![[#ENTRY_SIG]] = !{ptr @main1, ![[#INPUT_SIG:]], ![[#OUTPUT_SIG:]]} +// CHECK-DXIL: ![[#INPUT_SIG]] = !{![[#INPUT_ELEMENT:]]} +// CHECK-DXIL: ![[#OUTPUT_SIG]] = !{![[#OUTPUT_ELEMENT_0:]], ![[#OUTPUT_ELEMENT_1:]]} + // CHECK-SPIRV-DAG: ![[#METADATA_0]] = !{![[#METADATA_1:]]} // CHECK-SPIRV-DAG: ![[#METADATA_1]] = !{i32 30, i32 0} // | `- Location index diff --git a/clang/test/CodeGenHLSL/semantics/semantic.input.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.input.hlsl index 3c46eace082ee..3bd77d783b435 100644 --- a/clang/test/CodeGenHLSL/semantics/semantic.input.hlsl +++ b/clang/test/CodeGenHLSL/semantics/semantic.input.hlsl @@ -51,3 +51,14 @@ void main(S s) {} // CHECK: %[[E5:.*]] = call <4 x float> @llvm.dx.load.input.v4f32(i32 3, i32 5, i8 0, i32 poison) // CHECK: %[[E_ARRAY5:.*]] = insertvalue [2 x [3 x <4 x float>]] %[[E_ARRAY4]], <4 x float> %[[E5]], 1, 2 // CHECK: %[[S3:.*]] = insertvalue %struct.S %[[S2]], [2 x [3 x <4 x float>]] %[[E_ARRAY5]], 3 + +// CHECK: !dx.semantic.signatures = !{![[#ENTRY_SIG:]]} +// CHECK: ![[#ENTRY_SIG]] = !{ptr @main, ![[#INPUT_SIG:]], null} +// CHECK: ![[#INPUT_SIG]] = !{![[#A_SIG:]], ![[#B_SIG:]], ![[#D_SIG:]], ![[#E_SIG:]]} +// CHECK: ![[#A_SIG]] = !{i32 0, !"A", i32 9, i32 0, ![[#ZERO_INDEX:]], i32 0, i32 1, i8 1, i32 -1, i8 -1, i8 0, i8 0, i32 0} +// CHECK: ![[#ZERO_INDEX]] = !{i32 0} +// CHECK: ![[#B_SIG]] = !{i32 1, !"B", i32 9, i32 0, ![[#ZERO_INDEX]], i32 0, i32 1, i8 4, i32 -1, i8 -1, i8 0, i8 0, i32 0} +// CHECK: ![[#D_SIG]] = !{i32 2, !"D", i32 9, i32 0, ![[#D_INDICES:]], i32 0, i32 5, i8 1, i32 -1, i8 -1, i8 0, i8 0, i32 0} +// CHECK: ![[#D_INDICES]] = !{i32 0, i32 1, i32 2, i32 3, i32 4} +// CHECK: ![[#E_SIG]] = !{i32 3, !"E", i32 9, i32 0, ![[#E_INDICES:]], i32 0, i32 6, i8 4, i32 -1, i8 -1, i8 0, i8 0, i32 0} +// CHECK: ![[#E_INDICES]] = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5} diff --git a/clang/test/CodeGenHLSL/semantics/semantic.output.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.output.hlsl index fdb195899ca97..54e9aa83cda0b 100644 --- a/clang/test/CodeGenHLSL/semantics/semantic.output.hlsl +++ b/clang/test/CodeGenHLSL/semantics/semantic.output.hlsl @@ -54,3 +54,14 @@ S main() { // CHECK: call void @llvm.dx.store.output.v4f32(i32 3, i32 4, i8 0, <4 x float> %[[E11]]) // CHECK: %[[E12:.*]] = extractvalue [2 x [3 x <4 x float>]] %[[E]], 1, 2 // CHECK: call void @llvm.dx.store.output.v4f32(i32 3, i32 5, i8 0, <4 x float> %[[E12]]) + +// CHECK: !dx.semantic.signatures = !{![[#ENTRY_SIG:]]} +// CHECK: ![[#ENTRY_SIG]] = !{ptr @main, null, ![[#OUTPUT_SIG:]]} +// CHECK: ![[#OUTPUT_SIG]] = !{![[#A_SIG:]], ![[#B_SIG:]], ![[#D_SIG:]], ![[#E_SIG:]]} +// CHECK: ![[#A_SIG]] = !{i32 0, !"A", i32 9, i32 0, ![[#ZERO_INDEX:]], i32 0, i32 1, i8 1, i32 -1, i8 -1, i8 0, i8 0, i32 0} +// CHECK: ![[#ZERO_INDEX]] = !{i32 0} +// CHECK: ![[#B_SIG]] = !{i32 1, !"B", i32 9, i32 0, ![[#ZERO_INDEX]], i32 0, i32 1, i8 4, i32 -1, i8 -1, i8 0, i8 0, i32 0} +// CHECK: ![[#D_SIG]] = !{i32 2, !"D", i32 9, i32 0, ![[#D_INDICES:]], i32 0, i32 5, i8 1, i32 -1, i8 -1, i8 0, i8 0, i32 0} +// CHECK: ![[#D_INDICES]] = !{i32 0, i32 1, i32 2, i32 3, i32 4} +// CHECK: ![[#E_SIG]] = !{i32 3, !"E", i32 9, i32 0, ![[#E_INDICES:]], i32 0, i32 6, i8 4, i32 -1, i8 -1, i8 0, i8 0, i32 0} +// CHECK: ![[#E_INDICES]] = !{i32 0, i32 1, i32 2, i32 3, i32 4, i32 5} diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLResource.h b/llvm/include/llvm/Frontend/HLSL/HLSLResource.h index 8849ba880ad11..3aa63744457a5 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLResource.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLResource.h @@ -16,6 +16,8 @@ #include "llvm/Support/DXILABI.h" namespace llvm { +class Type; + namespace hlsl { // For now we use DXIL ABI enum values directly. This may change in the future. @@ -24,6 +26,11 @@ using dxil::ResourceDimension; const unsigned CBufferRowSizeInBytes = 16U; +/// Converts a scalar or vector LLVM type to its DXIL element type. Integer +/// signedness must be supplied separately because LLVM integer types are +/// signless. +LLVM_ABI dxil::ElementType getDXILElementType(Type *Ty, bool IsSigned); + } // namespace hlsl } // namespace llvm diff --git a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h index c5be2516a7364..0d0da50189e53 100644 --- a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h +++ b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h @@ -14,6 +14,7 @@ #ifndef LLVM_FRONTEND_HLSL_SEMANTICSIGNATURES_H #define LLVM_FRONTEND_HLSL_SEMANTICSIGNATURES_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/DXContainer.h" @@ -53,6 +54,15 @@ struct SemanticSignatureElement { uint8_t DynIndexMask = 0; uint32_t GSStream = 0; + SemanticSignatureElement() = default; + SemanticSignatureElement(uint32_t SigId, StringRef SemanticName, + dxil::ElementType CompType, + dxbc::PSV::SemanticKind SemanticKind, + ArrayRef<uint32_t> SemanticIndices, uint8_t Cols) + : SigId(SigId), SemanticName(SemanticName), CompType(CompType), + SemanticKind(SemanticKind), SemanticIndices(SemanticIndices), + Rows(static_cast<uint32_t>(SemanticIndices.size())), Cols(Cols) {} + bool isAllocated() const { return StartRow != UnallocatedRow && StartCol != UnallocatedCol; } @@ -92,6 +102,8 @@ struct SemanticSignatureElement { LLVM_ABI MDNode *toMetadata(LLVMContext &Ctx) const; }; +LLVM_ABI dxbc::PSV::SemanticKind getSemanticKind(StringRef SemanticName); + } // namespace hlsl } // namespace llvm diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp index 413521ac64d61..7ec06ea0205f3 100644 --- a/llvm/lib/Analysis/DXILResource.cpp +++ b/llvm/lib/Analysis/DXILResource.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Frontend/HLSL/HLSLResource.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DiagnosticInfo.h" @@ -180,33 +181,6 @@ static StringRef getSamplerFeedbackTypeName(SamplerFeedbackType SFT) { llvm_unreachable("Unhandled SamplerFeedbackType"); } -static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned) { - // TODO: Handle unorm, snorm, and packed. - Ty = Ty->getScalarType(); - - if (Ty->isIntegerTy()) { - switch (Ty->getIntegerBitWidth()) { - case 16: - return IsSigned ? ElementType::I16 : ElementType::U16; - case 32: - return IsSigned ? ElementType::I32 : ElementType::U32; - case 64: - return IsSigned ? ElementType::I64 : ElementType::U64; - case 1: - default: - return ElementType::Invalid; - } - } else if (Ty->isFloatTy()) { - return ElementType::F32; - } else if (Ty->isDoubleTy()) { - return ElementType::F64; - } else if (Ty->isHalfTy()) { - return ElementType::F16; - } - - return ElementType::Invalid; -} - static dxil::ElementType toDXILStorageType(dxil::ElementType ET) { if (ET == dxil::ElementType::U64 || ET == dxil::ElementType::F64 || ET == dxil::ElementType::I64 || ET == dxil::ElementType::SNormF64 || @@ -271,7 +245,7 @@ static void formatTypeName(SmallString<64> &Dest, StringRef Name, } StringRef ElementName; - ElementType ET = toDXILElementType(ContainedType, IsSigned); + ElementType ET = hlsl::getDXILElementType(ContainedType, IsSigned); if (ET != ElementType::Invalid) { ElementName = getElementTypeNameForTemplate(ET); } else { @@ -577,7 +551,7 @@ ResourceTypeInfo::TypedInfo ResourceTypeInfo::getTyped() const { assert(isTyped() && "Not typed"); auto [ElTy, IsSigned] = getTypedElementType(Kind, HandleTy); - dxil::ElementType ET = toDXILElementType(ElTy, IsSigned); + dxil::ElementType ET = hlsl::getDXILElementType(ElTy, IsSigned); dxil::ElementType DXILStorageTy = toDXILStorageType(ET); uint32_t Count = 1; if (auto *VTy = dyn_cast<FixedVectorType>(ElTy)) diff --git a/llvm/lib/Frontend/HLSL/HLSLResource.cpp b/llvm/lib/Frontend/HLSL/HLSLResource.cpp index 970edb9710cb6..2b6cc11d393eb 100644 --- a/llvm/lib/Frontend/HLSL/HLSLResource.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLResource.cpp @@ -11,9 +11,34 @@ //===----------------------------------------------------------------------===// #include "llvm/Frontend/HLSL/HLSLResource.h" +#include "llvm/IR/DerivedTypes.h" using namespace llvm; using namespace llvm::hlsl; -// Intentionally empty; this file can be removed when more cpp files are added -// to the HLSLFrontend lib. +dxil::ElementType hlsl::getDXILElementType(Type *Ty, bool IsSigned) { + // TODO: Handle unorm, snorm, and packed. + Ty = Ty->getScalarType(); + + if (Ty->isIntegerTy()) { + switch (Ty->getIntegerBitWidth()) { + case 16: + return IsSigned ? dxil::ElementType::I16 : dxil::ElementType::U16; + case 32: + return IsSigned ? dxil::ElementType::I32 : dxil::ElementType::U32; + case 64: + return IsSigned ? dxil::ElementType::I64 : dxil::ElementType::U64; + case 1: + default: + return dxil::ElementType::Invalid; + } + } else if (Ty->isFloatTy()) { + return dxil::ElementType::F32; + } else if (Ty->isDoubleTy()) { + return dxil::ElementType::F64; + } else if (Ty->isHalfTy()) { + return dxil::ElementType::F16; + } + + return dxil::ElementType::Invalid; +} diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp index f7ea8eb9a6e56..48d68c68946d7 100644 --- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp +++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Frontend/HLSL/SemanticSignatures.h" +#include "llvm/ADT/Enum.h" #include "llvm/ADT/STLForwardCompat.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Metadata.h" @@ -42,6 +43,17 @@ Expected<uint64_t> extractInt(const MDNode *Node, unsigned OpId) { } } // namespace +dxbc::PSV::SemanticKind hlsl::getSemanticKind(StringRef SemanticName) { + if (!SemanticName.consume_front_insensitive("SV_")) + return dxbc::PSV::SemanticKind::Arbitrary; + + for (const auto &Kind : dxbc::PSV::getSemanticKinds()) + if (SemanticName.equals_insensitive(Kind.name())) + return Kind.value(); + + return dxbc::PSV::SemanticKind::Invalid; +} + Expected<SemanticSignatureElement> SemanticSignatureElement::fromMetadata(const MDNode *Node) { // Operand positions within a signature element metadata node. diff --git a/llvm/unittests/Frontend/HLSLSemanticSignatureMetadataTest.cpp b/llvm/unittests/Frontend/HLSLSemanticSignatureMetadataTest.cpp index 0638cf0f49692..d4ccadb455525 100644 --- a/llvm/unittests/Frontend/HLSLSemanticSignatureMetadataTest.cpp +++ b/llvm/unittests/Frontend/HLSLSemanticSignatureMetadataTest.cpp @@ -70,15 +70,31 @@ class HLSLSemanticSignatureMetadataTest : public testing::Test { // Success cases //===----------------------------------------------------------------------===// +TEST_F(HLSLSemanticSignatureMetadataTest, SemanticKindLookup) { + // Names without the "SV_" prefix denote user-defined semantics + EXPECT_EQ(getSemanticKind("TEXCOORD"), dxbc::PSV::SemanticKind::Arbitrary); + EXPECT_EQ(getSemanticKind(""), dxbc::PSV::SemanticKind::Arbitrary); + EXPECT_EQ(getSemanticKind("Target"), dxbc::PSV::SemanticKind::Arbitrary); + + // System value names are matched case-insensitively, prefix included + EXPECT_EQ(getSemanticKind("SV_Target"), dxbc::PSV::SemanticKind::Target); + EXPECT_EQ(getSemanticKind("sv_target"), dxbc::PSV::SemanticKind::Target); + EXPECT_EQ(getSemanticKind("Sv_TaRgEt"), dxbc::PSV::SemanticKind::Target); + EXPECT_EQ(getSemanticKind("SV_Position"), dxbc::PSV::SemanticKind::Position); + + // An unrecognized system value name is invalid rather than arbitrary + EXPECT_EQ(getSemanticKind("SV_NotASemantic"), + dxbc::PSV::SemanticKind::Invalid); + EXPECT_EQ(getSemanticKind("SV_"), dxbc::PSV::SemanticKind::Invalid); +} + TEST_F(HLSLSemanticSignatureMetadataTest, StructHelpers) { - SemanticSignatureElement Elem; - Elem.SigId = 0; - Elem.CompType = dxil::ElementType::F32; - Elem.SemanticKind = dxbc::PSV::SemanticKind::Arbitrary; - Elem.Rows = 1; + SemanticSignatureElement Elem(/*SigId=*/0, "TEXCOORD", dxil::ElementType::F32, + dxbc::PSV::SemanticKind::Arbitrary, + /*SemanticIndices=*/{0}, /*Cols=*/4); + EXPECT_EQ(Elem.Rows, 1u); EXPECT_FALSE(Elem.isAllocated()); - Elem.Cols = 4; Elem.StartRow = 0; Elem.StartCol = 0; EXPECT_TRUE(Elem.isAllocated()); @@ -389,20 +405,11 @@ TEST_F(HLSLSemanticSignatureMetadataTest, MetadataToElementIndicesRowMismatch) { // A fully populated element emits all 13 operands in order TEST_F(HLSLSemanticSignatureMetadataTest, ElementToMetadata) { - SemanticSignatureElement Elem; - Elem.SigId = 1; - Elem.SemanticName = "TEXCOORD"; - Elem.CompType = dxil::ElementType::F32; - Elem.SemanticKind = dxbc::PSV::SemanticKind::Arbitrary; - Elem.SemanticIndices = {0, 1}; - Elem.InterpMode = dxbc::PSV::InterpolationMode::Undefined; - Elem.Rows = 2; - Elem.Cols = 4; + SemanticSignatureElement Elem(/*SigId=*/1, "TEXCOORD", dxil::ElementType::F32, + dxbc::PSV::SemanticKind::Arbitrary, + /*SemanticIndices=*/{0, 1}, /*Cols=*/4); Elem.StartRow = 1; Elem.StartCol = 0; - Elem.UsageMask = 0; - Elem.DynIndexMask = 0; - Elem.GSStream = 0; MDNode *Node = Elem.toMetadata(Ctx); ASSERT_EQ(Node->getNumOperands(), 13u); @@ -423,14 +430,10 @@ TEST_F(HLSLSemanticSignatureMetadataTest, ElementToMetadata) { // System value, non-zero masks and a non-zero stream index are emitted TEST_F(HLSLSemanticSignatureMetadataTest, ElementToMetadataSystemValue) { - SemanticSignatureElement Elem; - Elem.SigId = 1; - Elem.SemanticName = "SV_Target"; - Elem.CompType = dxil::ElementType::F32; - Elem.SemanticKind = dxbc::PSV::SemanticKind::Target; - Elem.SemanticIndices = {1}; - Elem.Rows = 1; - Elem.Cols = 4; + SemanticSignatureElement Elem(/*SigId=*/1, "SV_Target", + dxil::ElementType::F32, + dxbc::PSV::SemanticKind::Target, + /*SemanticIndices=*/{1}, /*Cols=*/4); Elem.StartRow = 1; Elem.StartCol = 0; Elem.UsageMask = 0x7; @@ -449,14 +452,9 @@ TEST_F(HLSLSemanticSignatureMetadataTest, ElementToMetadataSystemValue) { // An unallocated element emits the row/col sentinels TEST_F(HLSLSemanticSignatureMetadataTest, ElementToMetadataUnallocated) { - SemanticSignatureElement Elem; - Elem.SigId = 0; - Elem.SemanticName = "POSITION"; - Elem.CompType = dxil::ElementType::F32; - Elem.SemanticKind = dxbc::PSV::SemanticKind::Arbitrary; - Elem.SemanticIndices = {0}; - Elem.Rows = 0; - Elem.Cols = 0; + SemanticSignatureElement Elem(/*SigId=*/0, "POSITION", dxil::ElementType::F32, + dxbc::PSV::SemanticKind::Arbitrary, + /*SemanticIndices=*/{0}, /*Cols=*/4); MDNode *Node = Elem.toMetadata(Ctx); ASSERT_EQ(Node->getNumOperands(), 13u); @@ -466,20 +464,13 @@ TEST_F(HLSLSemanticSignatureMetadataTest, ElementToMetadataUnallocated) { // Emitting then parsing yields an equivalent element TEST_F(HLSLSemanticSignatureMetadataTest, ElementRoundTrip) { - SemanticSignatureElement Elem; - Elem.SigId = 2; - Elem.SemanticName = "TEXCOORD"; - Elem.CompType = dxil::ElementType::F32; - Elem.SemanticKind = dxbc::PSV::SemanticKind::Arbitrary; - Elem.SemanticIndices = {1}; + SemanticSignatureElement Elem(/*SigId=*/2, "TEXCOORD", dxil::ElementType::F32, + dxbc::PSV::SemanticKind::Arbitrary, + /*SemanticIndices=*/{1}, /*Cols=*/4); Elem.InterpMode = dxbc::PSV::InterpolationMode::LinearNoperspective; - Elem.Rows = 1; - Elem.Cols = 4; Elem.StartRow = 2; Elem.StartCol = 0; Elem.UsageMask = 0x7; - Elem.DynIndexMask = 0; - Elem.GSStream = 0; Expected<SemanticSignatureElement> Parsed = SemanticSignatureElement::fromMetadata(Elem.toMetadata(Ctx)); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
