From f978240a9623e26e915541a953dc796062ae18bb Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Tue, 28 Jul 2026 13:32:18 -0500 Subject: [PATCH 1/3] [SM 6.10] Disable Work Graphs in SM 6.10 With the introduction of SM 6.10, we're disabling Work Graphs support. This is captured in the Dxil 1.10 specification in [PR #918] (https://github.com/microsoft/hlsl-specs/pull/918). Assisted-by: Copilot --- include/dxc/dxcapi.internal.h | 2 + .../clang/Basic/DiagnosticSemaKinds.td | 12 ++++ tools/clang/lib/AST/ASTContextHLSL.cpp | 33 +++++++--- tools/clang/lib/Sema/SemaHLSL.cpp | 26 ++++++-- tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp | 51 +++++++++++++--- .../hlsl/workgraph/ast-nodeinput.hlsl | 3 + .../hlsl/workgraph/ast-nodeoutput.hlsl | 4 ++ .../hlsl/workgraph/ast-rwnodeinput.hlsl | 3 + .../attributes/GroupSharedLimitNode.hlsl | 61 ------------------- .../attributes/GroupSharedLimitNodeError.hlsl | 58 ------------------ .../wave/group-wave-invalid-nodes.hlsl | 28 --------- .../intrinsics/wave/group-wave-nodes.hlsl | 41 ------------- .../hlsl/linalg/builtins/stage-errors.hlsl | 13 +--- .../ast-EmptyNodeOutputArrayTypes.hlsl | 2 + .../workgraph/ast-NodeOutputArrayTypes.hlsl | 6 ++ .../sm6_10_lib_6x_no_diagnostics.hlsl | 31 ++++++++++ .../workgraph/sm6_10_node_shader_removed.hlsl | 46 ++++++++++++++ tools/clang/unittests/HLSL/ExtensionTest.cpp | 59 +++++++++--------- utils/hct/gen_intrin_main.txt | 2 +- utils/hct/hctdb.py | 29 +++++++++ utils/hct/hctdb_instrhelp.py | 21 ++++--- 21 files changed, 272 insertions(+), 259 deletions(-) delete mode 100644 tools/clang/test/HLSLFileCheckLit/hlsl/entry/attributes/GroupSharedLimitNode.hlsl delete mode 100644 tools/clang/test/HLSLFileCheckLit/hlsl/entry/attributes/GroupSharedLimitNodeError.hlsl delete mode 100644 tools/clang/test/HLSLFileCheckLit/hlsl/intrinsics/wave/group-wave-invalid-nodes.hlsl delete mode 100644 tools/clang/test/HLSLFileCheckLit/hlsl/intrinsics/wave/group-wave-nodes.hlsl create mode 100644 tools/clang/test/SemaHLSL/hlsl/workgraph/sm6_10_lib_6x_no_diagnostics.hlsl create mode 100644 tools/clang/test/SemaHLSL/hlsl/workgraph/sm6_10_node_shader_removed.hlsl diff --git a/include/dxc/dxcapi.internal.h b/include/dxc/dxcapi.internal.h index 6dbb899376..4264f3f4f6 100644 --- a/include/dxc/dxcapi.internal.h +++ b/include/dxc/dxcapi.internal.h @@ -201,6 +201,8 @@ struct HLSL_INTRINSIC { // type UINT uNumArgs; // Count of arguments in pArgs. const HLSL_INTRINSIC_ARGUMENT *pArgs; // Pointer to first argument. + UINT MaxShaderModel; // Encoded maximum shader model, 0 = no maximum + // (Major << 4) + (Minor & 0xf) }; /////////////////////////////////////////////////////////////////////////////// diff --git a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index dba557e509..bca27c7dcd 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7682,6 +7682,18 @@ def warn_hlsl_builtin_constant_unavailable: Warning< def warn_hlsl_builtin_type_unavailable: Warning< "potential misuse of built-in type %0 in shader model %1; introduced" " in shader model %2">, DefaultError, InGroup; +def warn_hlsl_builtin_constant_removed: Warning< + "built-in constant %0 is unavailable in shader model %1; it was removed" + " in shader model %2">, InGroup; +def warn_hlsl_builtin_type_removed: Warning< + "built-in type %0 is unavailable in shader model %1; it was removed" + " in shader model %2">, DefaultError, InGroup; +def warn_hlsl_intrinsic_removed: Warning< + "intrinsic %0 potentially used by '%1' is unavailable; it was removed" + " in shader model %2">, DefaultError, InGroup; +def warn_hlsl_node_shader_removed: Warning< + "node shaders and other Work Graphs functionality are not supported" + " when targeting shader model %0">, DefaultError, InGroup; def err_hlsl_unsupported_char_literal : Error< "unsupported style of char literal - use a single-character char-based literal">; def err_hlsl_unsupported_clipplane_argument_expression : Error< diff --git a/tools/clang/lib/AST/ASTContextHLSL.cpp b/tools/clang/lib/AST/ASTContextHLSL.cpp index 517be3c8c3..1898aae7e7 100644 --- a/tools/clang/lib/AST/ASTContextHLSL.cpp +++ b/tools/clang/lib/AST/ASTContextHLSL.cpp @@ -472,6 +472,25 @@ static void AddRecordSubscriptAccess(clang::ASTContext &Ctx, AddRecordAccessMethod(Ctx, RD, ReturnTy, false, true, true); } +AvailabilityAttr *ConstructAvailabilityAttribute( + clang::ASTContext &context, VersionTuple Introduced, + VersionTuple Deprecated = VersionTuple(), + VersionTuple Obsoleted = VersionTuple()) { + AvailabilityAttr *AAttr = AvailabilityAttr::CreateImplicit( + context, &context.Idents.get(""), Introduced, Deprecated, Obsoleted, + false, ""); + return AAttr; +} + +// Work graph node record objects: available SM6.8, deprecated SM6.9, +// obsoleted SM6.10. +static AvailabilityAttr * +ConstructNodeRecordAvailabilityAttribute(clang::ASTContext &context) { + return ConstructAvailabilityAttribute(context, VersionTuple(6, 8), + VersionTuple(6, 9), + VersionTuple(6, 10)); +} + /// Adds up-front support for HLSL *NodeOutputRecords template /// types. void hlsl::AddHLSLNodeOutputRecordTemplate( @@ -496,6 +515,8 @@ void hlsl::AddHLSLNodeOutputRecordTemplate( typeDeclBuilder.getRecordDecl()->addAttr( HLSLNodeObjectAttr::CreateImplicit(context, Type)); + typeDeclBuilder.getRecordDecl()->addAttr( + ConstructNodeRecordAvailabilityAttribute(context)); QualType elementType = context.getTemplateTypeParmType( 0, 0, ParameterPackFalse, outputTemplateParamDecl); @@ -546,14 +567,6 @@ hlsl::DeclareRecordTypeWithHandle(ASTContext &context, StringRef name, return typeDeclBuilder.getRecordDecl(); } -AvailabilityAttr *ConstructAvailabilityAttribute(clang::ASTContext &context, - VersionTuple Introduced) { - AvailabilityAttr *AAttr = AvailabilityAttr::CreateImplicit( - context, &context.Idents.get(""), clang::VersionTuple(6, 9), - clang::VersionTuple(), clang::VersionTuple(), false, ""); - return AAttr; -} - // creates a global static constant unsigned integer with value. // equivalent to: static const uint name = val; static void AddConstUInt(clang::ASTContext &context, DeclContext *DC, @@ -1355,6 +1368,8 @@ CXXRecordDecl *hlsl::DeclareNodeOrRecordType( Builder.getRecordDecl()->addAttr( HLSLNodeObjectAttr::CreateImplicit(Ctx, Type)); + Builder.getRecordDecl()->addAttr( + ConstructNodeRecordAvailabilityAttribute(Ctx)); if (IsRecordTypeTemplate) { QualType ParamTy = QualType(TyParamDecl->getTypeForDecl(), 0); @@ -1488,6 +1503,8 @@ CXXRecordDecl *hlsl::DeclareNodeOutputArray(clang::ASTContext &Ctx, Builder.getRecordDecl()->addAttr( HLSLNodeObjectAttr::CreateImplicit(Ctx, Type)); + Builder.getRecordDecl()->addAttr( + ConstructNodeRecordAvailabilityAttribute(Ctx)); QualType ResultType; if (IsRecordTypeTemplate) { diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index f818cbcb46..e19897e8f7 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -2090,12 +2090,28 @@ static void AddHLSLIntrinsicAttr(FunctionDecl *FD, ASTContext &context, FD->addAttr(PureAttr::CreateImplicit(context)); if (pIntrinsic->Flags & INTRIN_FLAG_IS_WAVE) FD->addAttr(HLSLWaveSensitiveAttr::CreateImplicit(context)); - if (pIntrinsic->MinShaderModel) { - unsigned Major = pIntrinsic->MinShaderModel >> 4; - unsigned Minor = pIntrinsic->MinShaderModel & 0xF; + if (pIntrinsic->MinShaderModel || pIntrinsic->MaxShaderModel) { + clang::VersionTuple Introduced; + if (pIntrinsic->MinShaderModel) { + unsigned Major = pIntrinsic->MinShaderModel >> 4; + unsigned Minor = pIntrinsic->MinShaderModel & 0xF; + Introduced = clang::VersionTuple(Major, Minor); + } + // The maximum shader model is the last one that still supports the + // intrinsic: it is deprecated there, and obsoleted in the next minor + // shader model version. We could give longer deprecation periods in the + // future if there is a need for that. + clang::VersionTuple Deprecated; + clang::VersionTuple Obsoleted; + if (pIntrinsic->MaxShaderModel) { + unsigned Major = pIntrinsic->MaxShaderModel >> 4; + unsigned Minor = pIntrinsic->MaxShaderModel & 0xF; + Deprecated = clang::VersionTuple(Major, Minor); + Obsoleted = clang::VersionTuple(Major, Minor + 1); + } FD->addAttr(AvailabilityAttr::CreateImplicit( - context, &context.Idents.get(""), clang::VersionTuple(Major, Minor), - clang::VersionTuple(), clang::VersionTuple(), false, "")); + context, &context.Idents.get(""), Introduced, Deprecated, Obsoleted, + false, "")); } } diff --git a/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp b/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp index ec723f374d..0ceed11c72 100644 --- a/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp +++ b/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp @@ -489,31 +489,57 @@ class HLSLReachableDiagnoseVisitor return SMVT >= AAttrVT; } + bool CheckObsoleted(VersionTuple ObsoletedVT) { + if (ObsoletedVT.empty() || IsTargetProfileLib6x(*sema)) + return true; + VersionTuple SMVT = VersionTuple(SM->GetMajor(), SM->GetMinor()); + return SMVT < ObsoletedVT; + } + void DiagnoseAvailability(AvailabilityAttr *AAttr, QualType Ty, SourceLocation Loc) { VersionTuple AAttrVT = AAttr->getIntroduced(); - if (CheckSMVersion(AAttrVT)) + if (!CheckSMVersion(AAttrVT)) { + sema->Diag(Loc, diag::warn_hlsl_builtin_type_unavailable) + << Ty << SM->GetName() << AAttrVT.getAsString(); return; + } - sema->Diag(Loc, diag::warn_hlsl_builtin_type_unavailable) - << Ty << SM->GetName() << AAttrVT.getAsString(); + VersionTuple ObsoletedVT = AAttr->getObsoleted(); + if (!CheckObsoleted(ObsoletedVT)) + sema->Diag(Loc, diag::warn_hlsl_builtin_type_removed) + << Ty << SM->GetName() << ObsoletedVT.getAsString(); } void DiagnoseAvailability(AvailabilityAttr *AAttr, NamedDecl *ND, SourceLocation Loc) { VersionTuple AAttrVT = AAttr->getIntroduced(); - if (CheckSMVersion(AAttrVT)) + if (!CheckSMVersion(AAttrVT)) { + if (isa(ND)) { + sema->Diag(Loc, diag::warn_hlsl_intrinsic_in_wrong_shader_model) + << ND->getQualifiedNameAsString() << EntryDecl + << AAttrVT.getAsString(); + return; + } + + sema->Diag(Loc, diag::warn_hlsl_builtin_constant_unavailable) + << ND << SM->GetName() << AAttrVT.getAsString(); + return; + } + + VersionTuple ObsoletedVT = AAttr->getObsoleted(); + if (CheckObsoleted(ObsoletedVT)) return; if (isa(ND)) { - sema->Diag(Loc, diag::warn_hlsl_intrinsic_in_wrong_shader_model) + sema->Diag(Loc, diag::warn_hlsl_intrinsic_removed) << ND->getQualifiedNameAsString() << EntryDecl - << AAttrVT.getAsString(); + << ObsoletedVT.getAsString(); return; } - sema->Diag(Loc, diag::warn_hlsl_builtin_constant_unavailable) - << ND << SM->GetName() << AAttrVT.getAsString(); + sema->Diag(Loc, diag::warn_hlsl_builtin_constant_removed) + << ND << SM->GetName() << ObsoletedVT.getAsString(); } clang::Sema *getSema() { return sema; } @@ -768,6 +794,15 @@ void hlsl::DiagnoseTranslationUnit(clang::Sema *self) { if (EntrySK == DXIL::ShaderKind::Library && IsTargetProfileLib6x(*self)) continue; + // Work Graphs (node shaders) were obsoleted in shader model 6.10. + // Declaring a node shader when targeting 6.10 or above is an error, + // regardless of whether any node record types are actually used. + if (EntrySK == DXIL::ShaderKind::Node && + shaderModel->IsSMAtLeast(6, 10) && !IsTargetProfileLib6x(*self)) { + self->Diag(FDecl->getLocation(), diag::warn_hlsl_node_shader_removed) + << shaderModel->GetName(); + } + // Visit all visited functions in call graph to collect illegal intrinsic // calls. HLSLReachableDiagnoseVisitor Visitor( diff --git a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-nodeinput.hlsl b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-nodeinput.hlsl index 7f5de6606b..d7a39c2c74 100644 --- a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-nodeinput.hlsl +++ b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-nodeinput.hlsl @@ -18,6 +18,7 @@ void node01(DispatchNodeInputRecord input) {} //CHECK-NEXT: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit struct DispatchNodeInputRecord definition //CHECK-NEXT: FinalAttr {{0x[0-9a-fA-F]+}} <> Implicit final //CHECK-NEXT: HLSLNodeObjectAttr {{0x[0-9a-fA-F]+}} <> Implicit DispatchNodeInputRecord +//CHECK-NEXT: AvailabilityAttr {{0x[0-9a-fA-F]+}} <> Implicit 6.8 6.9 6.10 "" //CHECK-NEXT: FieldDecl {{0x[0-9a-fA-F]+}} <> implicit h 'int' //CHECK-NEXT: CXXMethodDecl {{0x[0-9a-fA-F]+}} <> Get 'const recordtype &() const' //CHECK-NEXT: HLSLIntrinsicAttr {{0x[0-9a-fA-F]+}} <> Implicit "subscript" "" 0 @@ -34,6 +35,7 @@ void node02(GroupNodeInputRecords input) {} //CHECK-NEXT: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit struct GroupNodeInputRecords definition //CHECK-NEXT: FinalAttr {{0x[0-9a-fA-F]+}} <> Implicit final //CHECK-NEXT: HLSLNodeObjectAttr {{0x[0-9a-fA-F]+}} <> Implicit GroupNodeInputRecords +//CHECK-NEXT: AvailabilityAttr {{0x[0-9a-fA-F]+}} <> Implicit 6.8 6.9 6.10 "" //CHECK-NEXT: FieldDecl {{0x[0-9a-fA-F]+}} <> implicit h 'int' //CHECK-NEXT: CXXMethodDecl {{0x[0-9a-fA-F]+}} <> Get 'const recordtype &(unsigned int) const' //CHECK-NEXT: ParmVarDecl {{0x[0-9a-fA-F]+}} <> Index 'unsigned int' cinit @@ -63,6 +65,7 @@ void node03(ThreadNodeInputRecord input) {} //CHECK-NEXT: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit struct ThreadNodeInputRecord definition //CHECK-NEXT: FinalAttr {{0x[0-9a-fA-F]+}} <> Implicit final //CHECK-NEXT: HLSLNodeObjectAttr {{0x[0-9a-fA-F]+}} <> Implicit ThreadNodeInputRecord +//CHECK-NEXT: AvailabilityAttr {{0x[0-9a-fA-F]+}} <> Implicit 6.8 6.9 6.10 "" //CHECK-NEXT: FieldDecl {{0x[0-9a-fA-F]+}} <> implicit h 'int' //CHECK-NEXT: CXXMethodDecl {{0x[0-9a-fA-F]+}} <> Get 'const recordtype &() const' //CHECK-NEXT: HLSLIntrinsicAttr {{0x[0-9a-fA-F]+}} <> Implicit "subscript" "" 0 diff --git a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-nodeoutput.hlsl b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-nodeoutput.hlsl index 423db5292f..89e17e5d47 100644 --- a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-nodeoutput.hlsl +++ b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-nodeoutput.hlsl @@ -23,6 +23,7 @@ void node01(NodeOutput output) //CHECK-NEXT: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit struct GroupNodeOutputRecords definition //CHECK-NEXT: FinalAttr {{0x[0-9a-fA-F]+}} <> Implicit final //CHECK-NEXT: HLSLNodeObjectAttr {{0x[0-9a-fA-F]+}} <> Implicit GroupNodeOutputRecords +//CHECK-NEXT: AvailabilityAttr {{0x[0-9a-fA-F]+}} <> Implicit 6.8 6.9 6.10 "" //CHECK-NEXT: FieldDecl {{0x[0-9a-fA-F]+}} <> implicit h 'int' //CHECK-NEXT: CXXMethodDecl {{0x[0-9a-fA-F]+}} <> operator[] 'recordType &(unsigned int)' //CHECK-NEXT: ParmVarDecl {{0x[0-9a-fA-F]+}} <> Index 'unsigned int' @@ -54,6 +55,7 @@ void node01(NodeOutput output) //CHECK-NEXT: TemplateArgument type 'RECORD' //CHECK-NEXT: FinalAttr {{0x[0-9a-fA-F]+}} <> Implicit final //CHECK-NEXT: HLSLNodeObjectAttr {{0x[0-9a-fA-F]+}} <> Implicit GroupNodeOutputRecords +//CHECK-NEXT: AvailabilityAttr {{0x[0-9a-fA-F]+}} <> Implicit 6.8 6.9 6.10 "" //CHECK-NEXT: FieldDecl {{0x[0-9a-fA-F]+}} <> implicit h 'int' //CHECK-NEXT: CXXMethodDecl {{0x[0-9a-fA-F]+}} <> operator[] 'RECORD &(unsigned int)' //CHECK-NEXT: ParmVarDecl {{0x[0-9a-fA-F]+}} <> Index 'unsigned int' @@ -95,6 +97,7 @@ void node02(NodeOutput output) //CHECK-NEXT: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit struct ThreadNodeOutputRecords definition //CHECK-NEXT: FinalAttr {{0x[0-9a-fA-F]+}} <> Implicit final //CHECK-NEXT: HLSLNodeObjectAttr {{0x[0-9a-fA-F]+}} <> Implicit ThreadNodeOutputRecords +//CHECK-NEXT: AvailabilityAttr {{0x[0-9a-fA-F]+}} <> Implicit 6.8 6.9 6.10 "" //CHECK-NEXT: FieldDecl {{0x[0-9a-fA-F]+}} <> implicit h 'int' //CHECK-NEXT: CXXMethodDecl {{0x[0-9a-fA-F]+}} <> operator[] 'recordType &(unsigned int)' //CHECK-NEXT: ParmVarDecl {{0x[0-9a-fA-F]+}} <> Index 'unsigned int' @@ -126,6 +129,7 @@ void node02(NodeOutput output) //CHECK-NEXT: TemplateArgument type 'RECORD' //CHECK-NEXT: FinalAttr {{0x[0-9a-fA-F]+}} <> Implicit final //CHECK-NEXT: HLSLNodeObjectAttr {{0x[0-9a-fA-F]+}} <> Implicit ThreadNodeOutputRecords +//CHECK-NEXT: AvailabilityAttr {{0x[0-9a-fA-F]+}} <> Implicit 6.8 6.9 6.10 "" //CHECK-NEXT: FieldDecl {{0x[0-9a-fA-F]+}} <> implicit h 'int' //CHECK-NEXT: CXXMethodDecl {{0x[0-9a-fA-F]+}} <> operator[] 'RECORD &(unsigned int)' //CHECK-NEXT: ParmVarDecl {{0x[0-9a-fA-F]+}} <> Index 'unsigned int' diff --git a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-rwnodeinput.hlsl b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-rwnodeinput.hlsl index fb34e2094a..1593226f9c 100644 --- a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-rwnodeinput.hlsl +++ b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/ast-rwnodeinput.hlsl @@ -18,6 +18,7 @@ void node01(RWDispatchNodeInputRecord input) {} //CHECK-NEXT: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit struct RWDispatchNodeInputRecord definition //CHECK-NEXT: FinalAttr {{0x[0-9a-fA-F]+}} <> Implicit final //CHECK-NEXT: HLSLNodeObjectAttr {{0x[0-9a-fA-F]+}} <> Implicit RWDispatchNodeInputRecord +//CHECK-NEXT: AvailabilityAttr {{0x[0-9a-fA-F]+}} <> Implicit 6.8 6.9 6.10 "" //CHECK-NEXT: FieldDecl {{0x[0-9a-fA-F]+}} <> implicit h 'int' //CHECK-NEXT: CXXMethodDecl {{0x[0-9a-fA-F]+}} <> Get 'recordtype &()' //CHECK-NEXT: HLSLIntrinsicAttr {{0x[0-9a-fA-F]+}} <> Implicit "subscript" "" 0 @@ -40,6 +41,7 @@ void node02(RWGroupNodeInputRecords input) {} //CHECK-NEXT: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit struct RWGroupNodeInputRecords definition //CHECK-NEXT: FinalAttr {{0x[0-9a-fA-F]+}} <> Implicit final //CHECK-NEXT: HLSLNodeObjectAttr {{0x[0-9a-fA-F]+}} <> Implicit RWGroupNodeInputRecords +//CHECK-NEXT: AvailabilityAttr {{0x[0-9a-fA-F]+}} <> Implicit 6.8 6.9 6.10 "" //CHECK-NEXT: FieldDecl {{0x[0-9a-fA-F]+}} <> implicit h 'int' //CHECK-NEXT: CXXMethodDecl {{0x[0-9a-fA-F]+}} <> Get 'recordtype &(unsigned int)' //CHECK-NEXT: ParmVarDecl {{0x[0-9a-fA-F]+}} <> Index 'unsigned int' cinit @@ -78,6 +80,7 @@ void node03(RWThreadNodeInputRecord input) {} //CHECK-NEXT: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit struct RWThreadNodeInputRecord definition //CHECK-NEXT: FinalAttr {{0x[0-9a-fA-F]+}} <> Implicit final //CHECK-NEXT: HLSLNodeObjectAttr {{0x[0-9a-fA-F]+}} <> Implicit RWThreadNodeInputRecord +//CHECK-NEXT: AvailabilityAttr {{0x[0-9a-fA-F]+}} <> Implicit 6.8 6.9 6.10 "" //CHECK-NEXT: FieldDecl {{0x[0-9a-fA-F]+}} <> implicit h 'int' //CHECK-NEXT: CXXMethodDecl {{0x[0-9a-fA-F]+}} <> Get 'recordtype &()' //CHECK-NEXT: HLSLIntrinsicAttr {{0x[0-9a-fA-F]+}} <> Implicit "subscript" "" 0 diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/entry/attributes/GroupSharedLimitNode.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/entry/attributes/GroupSharedLimitNode.hlsl deleted file mode 100644 index dbbb99fd9d..0000000000 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/entry/attributes/GroupSharedLimitNode.hlsl +++ /dev/null @@ -1,61 +0,0 @@ -// REQUIRES: dxil-1-10 - -// PASS: usage <= default (no limit) -// RUN: %dxc -T lib_6_10 -DGSM_DWORDS=8192 %s | FileCheck %s - -// PASS: default < usage <= limit -// RUN: %dxc -T lib_6_10 -DGSM_DWORDS=9216 -DUSE_GROUP_SHARED_LIMIT -DLIMIT_BYTES=36864 %s | FileCheck %s - -// PASS: no usage, limit=0 (edge case) -// RUN: %dxc -T lib_6_10 -DNO_GSM -DUSE_GROUP_SHARED_LIMIT -DLIMIT_BYTES=0 %s | FileCheck %s - -// PASS: limit == usage < default -// RUN: %dxc -T lib_6_10 -DGSM_DWORDS=4096 -DUSE_GROUP_SHARED_LIMIT -DLIMIT_BYTES=16384 %s | FileCheck %s - -// CHECK: define void @NodeMain() - -#define NUM_THREADS 1024 - -#ifndef NO_GSM -#ifndef GSM_DWORDS -#define GSM_DWORDS 8192 -#endif -groupshared uint g_testBuffer[GSM_DWORDS]; -#endif - -RWStructuredBuffer g_output : register(u0); - -struct MY_INPUT_RECORD { - uint data; -}; - -[Shader("node")] -[NodeLaunch("broadcasting")] -[NodeDispatchGrid(2, 1, 1)] -[NumThreads(NUM_THREADS, 1, 1)] -#ifdef USE_GROUP_SHARED_LIMIT -[GroupSharedLimit(LIMIT_BYTES)] -#endif -void NodeMain(DispatchNodeInputRecord myInput) -{ - uint tid = myInput.Get().data; - -#ifndef NO_GSM - uint iterations = GSM_DWORDS / NUM_THREADS; - - for (uint i = 0; i < iterations; i++) - { - uint index = tid + i * NUM_THREADS; - g_testBuffer[index] = index; - } - - GroupMemoryBarrierWithGroupSync(); - - // Write the shared data to the output buffer - for (uint j = 0; j < iterations; j++) - { - uint index = tid + j * NUM_THREADS; - g_output[index] = g_testBuffer[index]; - } -#endif -} diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/entry/attributes/GroupSharedLimitNodeError.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/entry/attributes/GroupSharedLimitNodeError.hlsl deleted file mode 100644 index 49c28b74a2..0000000000 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/entry/attributes/GroupSharedLimitNodeError.hlsl +++ /dev/null @@ -1,58 +0,0 @@ -// REQUIRES: dxil-1-10 - -// FAIL: default < limit < usage (36864 < 40960) -// RUN: not %dxc -T lib_6_10 -DGSM_DWORDS=10240 -DUSE_GROUP_SHARED_LIMIT -DLIMIT_BYTES=36864 %s 2>&1 | FileCheck %s --check-prefix=CHECK-FAIL1 -// CHECK-FAIL1: Total Thread Group Shared Memory used by 'NodeMain' is 40960, exceeding explicit limit: 36864. - -// FAIL: default < usage (no limit) (32768 < 36864) -// RUN: not %dxc -T lib_6_10 -DGSM_DWORDS=9216 %s 2>&1 | FileCheck %s --check-prefix=CHECK-FAIL2 -// CHECK-FAIL2: Total Thread Group Shared Memory used by 'NodeMain' is 36864, exceeding maximum: 32768 - -// FAIL: limit < usage < default (8192 < 16384 < 32768) -// RUN: not %dxc -T lib_6_10 -DGSM_DWORDS=4096 -DUSE_GROUP_SHARED_LIMIT -DLIMIT_BYTES=8192 %s 2>&1 | FileCheck %s --check-prefix=CHECK-FAIL3 -// CHECK-FAIL3: Total Thread Group Shared Memory used by 'NodeMain' is 16384, exceeding explicit limit: 8192. - -// FAIL: limit=0 < usage < default (0 < 16384 < 32768) (edge case) -// RUN: not %dxc -T lib_6_10 -DGSM_DWORDS=4096 -DUSE_GROUP_SHARED_LIMIT -DLIMIT_BYTES=0 %s 2>&1 | FileCheck %s --check-prefix=CHECK-FAIL4 -// CHECK-FAIL4: Total Thread Group Shared Memory used by 'NodeMain' is 16384, exceeding explicit limit: 0. - -#define NUM_THREADS 1024 - -#ifndef GSM_DWORDS -#define GSM_DWORDS 8192 -#endif -groupshared uint g_testBuffer[GSM_DWORDS]; - -RWStructuredBuffer g_output : register(u0); - -struct MY_INPUT_RECORD { - uint data; -}; - -[Shader("node")] -[NodeLaunch("broadcasting")] -[NodeDispatchGrid(2, 1, 1)] -[NumThreads(NUM_THREADS, 1, 1)] -#ifdef USE_GROUP_SHARED_LIMIT -[GroupSharedLimit(LIMIT_BYTES)] -#endif -void NodeMain(DispatchNodeInputRecord myInput) -{ - uint tid = myInput.Get().data; - uint iterations = GSM_DWORDS / NUM_THREADS; - - for (uint i = 0; i < iterations; i++) - { - uint index = tid + i * NUM_THREADS; - g_testBuffer[index] = index; - } - - GroupMemoryBarrierWithGroupSync(); - - // Write the shared data to the output buffer - for (uint j = 0; j < iterations; j++) - { - uint index = tid + j * NUM_THREADS; - g_output[index] = g_testBuffer[index]; - } -} diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/intrinsics/wave/group-wave-invalid-nodes.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/intrinsics/wave/group-wave-invalid-nodes.hlsl deleted file mode 100644 index ea85b59ef2..0000000000 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/intrinsics/wave/group-wave-invalid-nodes.hlsl +++ /dev/null @@ -1,28 +0,0 @@ -// REQUIRES: dxil-1-10 - -// RUN: not %dxc -T lib_6_10 %s 2>&1 | FileCheck %s - -// CHECK-DAG: error: Function requires a visible group, but is called from a shader without one. - -struct InputRecord { - uint value; -}; - -struct OutputRecord { - uint value; -}; - -RWStructuredBuffer output : register(u0); - -// Thread launch - no thread group, should FAIL -[Shader("node")] -[NodeLaunch("thread")] -void ThreadNode( - RWThreadNodeInputRecord inputData, - [MaxRecords(1)] NodeOutput outputData) { - uint waveIdx = GetGroupWaveIndex(); - uint waveCount = GetGroupWaveCount(); - ThreadNodeOutputRecords outRec = outputData.GetThreadNodeOutputRecords(1); - outRec.Get().value = waveIdx + waveCount; - outRec.OutputComplete(); -} diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/intrinsics/wave/group-wave-nodes.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/intrinsics/wave/group-wave-nodes.hlsl deleted file mode 100644 index b88c8c23d2..0000000000 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/intrinsics/wave/group-wave-nodes.hlsl +++ /dev/null @@ -1,41 +0,0 @@ -// REQUIRES: dxil-1-10 - -// RUN: %dxc -T lib_6_10 %s 2>&1 | FileCheck %s - -// CHECK-DAG: define void @BroadcastingNode -// CHECK-DAG: define void @CoalescingNode - -struct InputRecord { - uint value; -}; - -struct OutputRecord { - uint value; -}; - -RWStructuredBuffer output : register(u0); - -// Broadcasting launch - has thread group, should work -[Shader("node")] -[NodeLaunch("broadcasting")] -[NodeDispatchGrid(1,1,1)] -[NumThreads(8,1,1)] -void BroadcastingNode(DispatchNodeInputRecord inputData) { - uint waveIdx = GetGroupWaveIndex(); - uint waveCount = GetGroupWaveCount(); - output[0] = waveIdx + waveCount + inputData.Get().value; -} - -// Coalescing launch - has thread group, should work -[Shader("node")] -[NodeLaunch("coalescing")] -[NumThreads(8,1,1)] -void CoalescingNode( - [MaxRecords(8)] GroupNodeInputRecords inputData, - [MaxRecords(8)] NodeOutput outputData) { - uint waveIdx = GetGroupWaveIndex(); - uint waveCount = GetGroupWaveCount(); - GroupNodeOutputRecords outRec = outputData.GetGroupNodeOutputRecords(1); - outRec.Get().value = waveIdx + waveCount; - outRec.OutputComplete(); -} \ No newline at end of file diff --git a/tools/clang/test/SemaHLSL/hlsl/linalg/builtins/stage-errors.hlsl b/tools/clang/test/SemaHLSL/hlsl/linalg/builtins/stage-errors.hlsl index 5eb181a70c..8a47604644 100644 --- a/tools/clang/test/SemaHLSL/hlsl/linalg/builtins/stage-errors.hlsl +++ b/tools/clang/test/SemaHLSL/hlsl/linalg/builtins/stage-errors.hlsl @@ -90,9 +90,8 @@ void CallFunction() __builtin_LinAlg_Convert(outVec, vecA, 1, 2); __builtin_LinAlg_VectorAccumulateToDescriptor(buf, 0, 64, vecA); - // expected-error@+12{{builtin unavailable in shader stage 'pixel' (requires 'compute', 'mesh' or 'amplification')}} - // expected-error@+11{{builtin unavailable in shader stage 'vertex' (requires 'compute', 'mesh' or 'amplification')}} - // expected-error@+10{{builtin unavailable in shader stage 'node' (requires 'compute', 'mesh' or 'amplification')}} + // expected-error@+11{{builtin unavailable in shader stage 'pixel' (requires 'compute', 'mesh' or 'amplification')}} + // expected-error@+10{{builtin unavailable in shader stage 'vertex' (requires 'compute', 'mesh' or 'amplification')}} // expected-error@+9{{builtin unavailable in shader stage 'raygeneration' (requires 'compute', 'mesh' or 'amplification')}} // expected-error@+8{{builtin unavailable in shader stage 'intersection' (requires 'compute', 'mesh' or 'amplification')}} // expected-error@+7{{builtin unavailable in shader stage 'callable' (requires 'compute', 'mesh' or 'amplification')}} @@ -157,14 +156,6 @@ float4 mainVS(uint ix : SV_VertexID) : OUT { return 1.0; } -[shader("node")] -[nodedispatchgrid(8,1,1)] -[numthreads(64,2,2)] -// expected-note@+1{{entry function defined here}} -void mainNS() { - CallFunction(); -} - [shader("raygeneration")] // expected-note@+1{{entry function defined here}} void mainRG() { diff --git a/tools/clang/test/SemaHLSL/hlsl/workgraph/ast-EmptyNodeOutputArrayTypes.hlsl b/tools/clang/test/SemaHLSL/hlsl/workgraph/ast-EmptyNodeOutputArrayTypes.hlsl index aa5a7123f6..94c481247d 100644 --- a/tools/clang/test/SemaHLSL/hlsl/workgraph/ast-EmptyNodeOutputArrayTypes.hlsl +++ b/tools/clang/test/SemaHLSL/hlsl/workgraph/ast-EmptyNodeOutputArrayTypes.hlsl @@ -22,6 +22,7 @@ void node_2_0( // CHECK:|-CXXRecordDecl 0x{{.+}} <> implicit struct EmptyNodeOutput definition // CHECK-NEXT:| |-FinalAttr 0x{{.+}} <> Implicit final // CHECK-NEXT:| |-HLSLNodeObjectAttr 0x{{.+}} <> Implicit EmptyNodeOutput +// CHECK-NEXT:| |-AvailabilityAttr 0x{{.+}} <> Implicit 6.8 6.9 6.10 "" // CHECK-NEXT:| |-FieldDecl 0x{{.+}} <> implicit h 'int' // CHECK-NEXT:| |-FunctionTemplateDecl 0x{{.+}} <> GroupIncrementOutputCount // CHECK-NEXT:| | |-TemplateTypeParmDecl 0x{{.+}} <> class TResult @@ -46,6 +47,7 @@ void node_2_0( // CHECK:|-CXXRecordDecl 0x{{.+}} <> implicit referenced struct EmptyNodeOutputArray definition // CHECK-NEXT:| |-FinalAttr 0x{{.+}} <> Implicit final // CHECK-NEXT:| |-HLSLNodeObjectAttr 0x{{.+}} <> Implicit EmptyNodeOutputArray +// CHECK-NEXT:| |-AvailabilityAttr 0x{{.+}} <> Implicit 6.8 6.9 6.10 "" // CHECK-NEXT:| |-FieldDecl 0x{{.+}} <> implicit h 'int' // CHECK-NEXT:| `-CXXMethodDecl 0x[[SUB:[0-9a-f]+]] <> used operator[] 'EmptyNodeOutput (unsigned int)' // CHECK-NEXT:| |-ParmVarDecl 0x{{.+}} <> index 'unsigned int' diff --git a/tools/clang/test/SemaHLSL/hlsl/workgraph/ast-NodeOutputArrayTypes.hlsl b/tools/clang/test/SemaHLSL/hlsl/workgraph/ast-NodeOutputArrayTypes.hlsl index 6d381c5953..52b558a07a 100644 --- a/tools/clang/test/SemaHLSL/hlsl/workgraph/ast-NodeOutputArrayTypes.hlsl +++ b/tools/clang/test/SemaHLSL/hlsl/workgraph/ast-NodeOutputArrayTypes.hlsl @@ -25,6 +25,7 @@ void node_1_1( // CHECK-NEXT:| |-CXXRecordDecl 0x{{.+}} <> implicit struct ThreadNodeOutputRecords definition // CHECK-NEXT:| | |-FinalAttr 0x{{.+}} <> Implicit final // CHECK-NEXT:| | |-HLSLNodeObjectAttr 0x{{.+}} <> Implicit ThreadNodeOutputRecords +// CHECK-NEXT:| | |-AvailabilityAttr 0x{{.+}} <> Implicit 6.8 6.9 6.10 "" // CHECK-NEXT:| | |-FieldDecl 0x{{.+}} <> implicit h 'int' // CHECK-NEXT:| | |-CXXMethodDecl 0x{{.+}} <> operator[] 'recordType &(unsigned int)' // CHECK-NEXT:| | | |-ParmVarDecl 0x{{.+}} <> Index 'unsigned int' @@ -56,6 +57,7 @@ void node_1_1( // CHECK-NEXT:| |-TemplateArgument type 'RECORD1' // CHECK-NEXT:| |-FinalAttr 0x{{.+}} <> Implicit final // CHECK-NEXT:| |-HLSLNodeObjectAttr 0x{{.+}} <> Implicit ThreadNodeOutputRecords +// CHECK-NEXT:| |-AvailabilityAttr 0x{{.+}} <> Implicit 6.8 6.9 6.10 "" // CHECK-NEXT:| |-FieldDecl 0x{{.+}} <> implicit h 'int' // CHECK-NEXT:| |-CXXMethodDecl 0x{{.+}} <> operator[] 'RECORD1 &(unsigned int)' // CHECK-NEXT:| | |-ParmVarDecl 0x{{.+}} <> Index 'unsigned int' @@ -91,6 +93,7 @@ void node_1_1( // CHECK-NEXT:| |-CXXRecordDecl 0x{{.+}} <> implicit struct NodeOutput definition // CHECK-NEXT:| | |-FinalAttr 0x{{.+}} <> Implicit final // CHECK-NEXT:| | |-HLSLNodeObjectAttr 0x{{.+}} <> Implicit NodeOutput +// CHECK-NEXT:| | |-AvailabilityAttr 0x{{.+}} <> Implicit 6.8 6.9 6.10 "" // CHECK-NEXT:| | |-FieldDecl 0x{{.+}} <> implicit h 'int' // CHECK-NEXT:| | |-FunctionTemplateDecl 0x{{.+}} <> GetGroupNodeOutputRecords // CHECK-NEXT:| | | |-TemplateTypeParmDecl 0x{{.+}} <> class TResult @@ -109,6 +112,7 @@ void node_1_1( // CHECK-NEXT:| |-TemplateArgument type 'RECORD1' // CHECK-NEXT:| |-FinalAttr 0x{{.+}} <> Implicit final // CHECK-NEXT:| |-HLSLNodeObjectAttr 0x{{.+}} <> Implicit NodeOutput +// CHECK-NEXT:| |-AvailabilityAttr 0x{{.+}} <> Implicit 6.8 6.9 6.10 "" // CHECK-NEXT:| |-FieldDecl 0x{{.+}} <> implicit h 'int' // CHECK-NEXT:| |-FunctionTemplateDecl 0x{{.+}} <> GetGroupNodeOutputRecords // CHECK-NEXT:| | |-TemplateTypeParmDecl 0x{{.+}} <> class TResult @@ -135,6 +139,7 @@ void node_1_1( // CHECK-NEXT:| |-CXXRecordDecl 0x{{.+}} <> implicit struct NodeOutputArray definition // CHECK-NEXT:| | |-FinalAttr 0x{{.+}} <> Implicit final // CHECK-NEXT:| | |-HLSLNodeObjectAttr 0x{{.+}} <> Implicit NodeOutputArray +// CHECK-NEXT:| | |-AvailabilityAttr 0x{{.+}} <> Implicit 6.8 6.9 6.10 "" // CHECK-NEXT:| | |-FieldDecl 0x{{.+}} <> implicit h 'int' // CHECK-NEXT:| | `-CXXMethodDecl 0x{{.+}} <> operator[] 'NodeOutput (unsigned int)' // CHECK-NEXT:| | |-ParmVarDecl 0x{{.+}} <> index 'unsigned int' @@ -144,6 +149,7 @@ void node_1_1( // CHECK-NEXT:| |-TemplateArgument type 'RECORD1' // CHECK-NEXT:| |-FinalAttr 0x{{.+}} <> Implicit final // CHECK-NEXT:| |-HLSLNodeObjectAttr 0x{{.+}} <> Implicit NodeOutputArray +// CHECK-NEXT:| |-AvailabilityAttr 0x{{.+}} <> Implicit 6.8 6.9 6.10 "" // CHECK-NEXT:| |-FieldDecl 0x{{.+}} <> implicit h 'int' // CHECK-NEXT:| `-CXXMethodDecl 0x[[SUB:[0-9a-f]+]] <> used operator[] 'NodeOutput (unsigned int)' // CHECK-NEXT:| |-ParmVarDecl 0x{{.+}} <> index 'unsigned int' diff --git a/tools/clang/test/SemaHLSL/hlsl/workgraph/sm6_10_lib_6x_no_diagnostics.hlsl b/tools/clang/test/SemaHLSL/hlsl/workgraph/sm6_10_lib_6x_no_diagnostics.hlsl new file mode 100644 index 0000000000..d143147fad --- /dev/null +++ b/tools/clang/test/SemaHLSL/hlsl/workgraph/sm6_10_lib_6x_no_diagnostics.hlsl @@ -0,0 +1,31 @@ +// RUN: %dxc -T lib_6_x %s -verify + +// lib_6_x is an offline-linking-only target that defers final shader model +// availability checks to link time. Declaring node shaders of any launch +// type, and using node record types (including in exported library helper +// functions), must not produce any diagnostics when targeting lib_6_x, even +// though these are obsoleted at shader model 6.10. + +// expected-no-diagnostics + +struct RECORD +{ + uint a; +}; + +[Shader("node")] +[NodeLaunch("broadcasting")] +[NodeDispatchGrid(1,1,1)] +[NumThreads(1,1,1)] +void broadcasting_node(DispatchNodeInputRecord input) {} + +[Shader("node")] +[NodeLaunch("coalescing")] +[NumThreads(1,1,1)] +void coalescing_node() {} + +[Shader("node")] +[NodeLaunch("thread")] +void thread_node() {} + +export void HelperUsesNodeOutput(NodeOutput output) {} diff --git a/tools/clang/test/SemaHLSL/hlsl/workgraph/sm6_10_node_shader_removed.hlsl b/tools/clang/test/SemaHLSL/hlsl/workgraph/sm6_10_node_shader_removed.hlsl new file mode 100644 index 0000000000..b06e491548 --- /dev/null +++ b/tools/clang/test/SemaHLSL/hlsl/workgraph/sm6_10_node_shader_removed.hlsl @@ -0,0 +1,46 @@ +// RUN: %dxc -T lib_6_10 %s -verify + +// Work Graphs (node shaders) were obsoleted in shader model 6.10. Declaring a +// node shader of any launch type when targeting shader model 6.10 or above +// must be an error, regardless of whether any node record types are used. +// Using a node record type must also be an error, independent of whether the +// entry point declaring it is itself a node shader. + +struct RECORD +{ + uint a; +}; + +[Shader("node")] +[NodeLaunch("broadcasting")] +[NodeDispatchGrid(1,1,1)] +[NumThreads(1,1,1)] +// expected-error@+1{{node shaders and other Work Graphs functionality are not supported when targeting shader model lib_6_10}} +void broadcasting_node() {} + +[Shader("node")] +[NodeLaunch("coalescing")] +[NumThreads(1,1,1)] +// expected-error@+1{{node shaders and other Work Graphs functionality are not supported when targeting shader model lib_6_10}} +void coalescing_node() {} + +[Shader("node")] +[NodeLaunch("thread")] +// expected-error@+1{{node shaders and other Work Graphs functionality are not supported when targeting shader model lib_6_10}} +void thread_node() {} + +// Using a node record type is independently an error, on top of the node +// shader declaration error above. +[Shader("node")] +[NodeLaunch("broadcasting")] +[NodeDispatchGrid(1,1,1)] +[NumThreads(1,1,1)] +// expected-error@+2{{node shaders and other Work Graphs functionality are not supported when targeting shader model lib_6_10}} +// expected-error@+1{{built-in type 'DispatchNodeInputRecord' is unavailable in shader model lib_6_10; it was removed in shader model 6.10}} +void node_with_input(DispatchNodeInputRecord input) {} + +// A node record type used outside of a node shader entry point (e.g. in a +// library helper) is still an error at shader model 6.10. The helper must be +// exported so that it is checked even though nothing calls it. +// expected-error@+1{{built-in type 'NodeOutput' is unavailable in shader model lib_6_10; it was removed in shader model 6.10}} +export void HelperUsesNodeOutput(NodeOutput output) {} diff --git a/tools/clang/unittests/HLSL/ExtensionTest.cpp b/tools/clang/unittests/HLSL/ExtensionTest.cpp index 47d19a3e0d..b32644110b 100644 --- a/tools/clang/unittests/HLSL/ExtensionTest.cpp +++ b/tools/clang/unittests/HLSL/ExtensionTest.cpp @@ -204,86 +204,87 @@ Intrinsic Intrinsics[] = { {L"test_fn", DEFAULT_NAME, "r", - {1, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnArgs), TestFnArgs}}, + {1, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnArgs), TestFnArgs, 0}}, {L"test_proc", DEFAULT_NAME, "r", - {2, 0, 0, -1, countof(TestProcArgs), TestProcArgs}}, + {2, 0, 0, -1, countof(TestProcArgs), TestProcArgs, 0}}, {L"test_poly", "test_poly.$o", "r", {3, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnCustomArgs), - TestFnCustomArgs}}, + TestFnCustomArgs, 0}}, {L"test_int", "test_int", "r", - {4, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnIntArgs), TestFnIntArgs}}, + {4, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnIntArgs), TestFnIntArgs, + 0}}, {L"test_nolower", "test_nolower.$o", "n", {5, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnNoLowerArgs), - TestFnNoLowerArgs}}, + TestFnNoLowerArgs, 0}}, {L"test_pack_0", "test_pack_0.$o", "p", - {6, 0, 0, -1, countof(TestFnPack0), TestFnPack0}}, + {6, 0, 0, -1, countof(TestFnPack0), TestFnPack0, 0}}, {L"test_pack_1", "test_pack_1.$o", "p", - {7, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack1), TestFnPack1}}, + {7, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack1), TestFnPack1, 0}}, {L"test_pack_2", "test_pack_2.$o", "p", - {8, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack2), TestFnPack2}}, + {8, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack2), TestFnPack2, 0}}, {L"test_pack_3", "test_pack_3.$o", "p", - {9, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack3), TestFnPack3}}, + {9, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack3), TestFnPack3, 0}}, {L"test_pack_4", "test_pack_4.$o", "p", - {10, 0, 0, -1, countof(TestFnPack4), TestFnPack4}}, + {10, 0, 0, -1, countof(TestFnPack4), TestFnPack4, 0}}, {L"test_rand", "test_rand", "r", - {11, 0, 0, -1, countof(TestRand), TestRand}}, + {11, 0, 0, -1, countof(TestRand), TestRand, 0}}, {L"test_isinf", "test_isinf", "d", {13, INTRIN_FLAG_READ_ONLY | INTRIN_FLAG_READ_NONE, 0, -1, - countof(TestIsInf), TestIsInf}}, + countof(TestIsInf), TestIsInf, 0}}, {L"test_ibfe", "test_ibfe", "d", {14, INTRIN_FLAG_READ_ONLY | INTRIN_FLAG_READ_NONE, 0, -1, - countof(TestIBFE), TestIBFE}}, + countof(TestIBFE), TestIBFE, 0}}, // Make this intrinsic have the same opcode as an hlsl intrinsic with an // unsigned counterpart for testing purposes. {L"test_unsigned", "test_unsigned", "n", {static_cast(hlsl::IntrinsicOp::IOP_min), INTRIN_FLAG_READ_NONE, - 0, -1, countof(TestUnsigned), TestUnsigned}}, + 0, -1, countof(TestUnsigned), TestUnsigned, 0}}, {L"wave_proc", DEFAULT_NAME, "r", {16, INTRIN_FLAG_READ_NONE | INTRIN_FLAG_IS_WAVE, 0, -1, - countof(WaveProcArgs), WaveProcArgs}}, + countof(WaveProcArgs), WaveProcArgs, 0}}, {L"test_o_1", "test_o_1.$o:1", "r", {18, INTRIN_FLAG_READ_NONE | INTRIN_FLAG_IS_WAVE, 0, -1, - countof(TestOverloadArgs), TestOverloadArgs}}, + countof(TestOverloadArgs), TestOverloadArgs, 0}}, {L"test_o_2", "test_o_2.$o:2", "r", {19, INTRIN_FLAG_READ_NONE | INTRIN_FLAG_IS_WAVE, 0, -1, - countof(TestOverloadArgs), TestOverloadArgs}}, + countof(TestOverloadArgs), TestOverloadArgs, 0}}, {L"test_o_3", "test_o_3.$o:3", "r", {20, INTRIN_FLAG_READ_NONE | INTRIN_FLAG_IS_WAVE, 0, -1, - countof(TestOverloadArgs), TestOverloadArgs}}, + countof(TestOverloadArgs), TestOverloadArgs, 0}}, // custom lowering with both optional arguments and vector exploding. // Arg 0 = Opcode // Arg 1 = Pass as is @@ -294,17 +295,17 @@ Intrinsic Intrinsics[] = { "CustomLoadOp", "c:{\"default\" : \"0,1,2:?i1,3.0:?i32,3.1:?i32\"}", {21, INTRIN_FLAG_READ_ONLY, 0, -1, countof(TestCustomLoadOp), - TestCustomLoadOp}}, + TestCustomLoadOp, 0}}, {L"CustomLoadOp", "CustomLoadOp", "c:{\"default\" : \"0,1,2:?i1,3.0:?i32,3.1:?i32\"}", {21, INTRIN_FLAG_READ_ONLY, 0, -1, countof(TestCustomLoadOpBool), - TestCustomLoadOpBool}}, + TestCustomLoadOpBool, 0}}, {L"CustomLoadOp", "CustomLoadOp", "c:{\"default\" : \"0,1,2:?i1,3.0:?i32,3.1:?i32\"}", {21, INTRIN_FLAG_READ_ONLY, 0, -1, countof(TestCustomLoadOpSubscript), - TestCustomLoadOpSubscript}}, + TestCustomLoadOpSubscript, 0}}, }; Intrinsic BufferIntrinsics[] = { @@ -312,7 +313,7 @@ Intrinsic BufferIntrinsics[] = { "MyBufferOp", "m", {12, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestMyBufferOp), - TestMyBufferOp}}, + TestMyBufferOp, 0}}, }; // Test adding a method to an object that normally has no methods (SamplerState @@ -322,7 +323,7 @@ Intrinsic SamplerIntrinsics[] = { "MySamplerOp", "m", {15, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestMySamplerOp), - TestMySamplerOp}}, + TestMySamplerOp, 0}}, }; // Define a lowering string to target a common dxil extension operation defined @@ -356,12 +357,12 @@ Intrinsic Texture1DIntrinsics[] = { "MyTextureOp", MyTextureOp_LoweringInfo, {17, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestMyTexture1DOp_0), - TestMyTexture1DOp_0}}, + TestMyTexture1DOp_0, 0}}, {L"MyTextureOp", "MyTextureOp", MyTextureOp_LoweringInfo, {17, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestMyTexture1DOp_1), - TestMyTexture1DOp_1}}, + TestMyTexture1DOp_1, 0}}, }; Intrinsic Texture2DIntrinsics[] = { @@ -369,7 +370,7 @@ Intrinsic Texture2DIntrinsics[] = { "MyTextureOp", MyTextureOp_LoweringInfo, {17, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestMyTexture2DOp), - TestMyTexture2DOp}}, + TestMyTexture2DOp, 0}}, }; class IntrinsicTable { @@ -1508,7 +1509,7 @@ TEST_F(ExtensionTest, EvalAttributeCollision) { "collide_proc", "r", {static_cast(op), INTRIN_FLAG_READ_ONLY, 0, - -1, countof(Args), Args}}; + -1, countof(Args), Args, 0}}; Compiler c(m_dllSupport); c.RegisterIntrinsicTable(new TestIntrinsicTable(&Intrinsic, 1)); c.Compile(R"( @@ -1543,7 +1544,7 @@ TEST_F(ExtensionTest, NoUnwind) { {"value", AR_QUAL_IN, 1, LITEMPLATE_ANY, 1, LICOMPTYPE_NUMERIC, 1, IA_C}}; Intrinsic Intrinsic = { - L"test_proc", "test_proc", "r", {1, 0, 0, -1, countof(Args), Args}}; + L"test_proc", "test_proc", "r", {1, 0, 0, -1, countof(Args), Args, 0}}; Compiler c(m_dllSupport); c.RegisterIntrinsicTable(new TestIntrinsicTable(&Intrinsic, 1)); c.Compile(R"( @@ -1581,7 +1582,7 @@ TEST_F(ExtensionTest, DCE) { "test_proc", "r", {1, INTRIN_FLAG_READ_ONLY | INTRIN_FLAG_READ_NONE, 0, - -1, countof(Args), Args}}; + -1, countof(Args), Args, 0}}; Compiler c(m_dllSupport); c.RegisterIntrinsicTable(new TestIntrinsicTable(&Intrinsic, 1)); c.Compile(R"( diff --git a/utils/hct/gen_intrin_main.txt b/utils/hct/gen_intrin_main.txt index f9c08e434b..f6d2589874 100644 --- a/utils/hct/gen_intrin_main.txt +++ b/utils/hct/gen_intrin_main.txt @@ -385,7 +385,7 @@ $type2 [[rn]] select(in bool cond, in any_sampler t, in $type2 f); void [[]] Barrier(in uint MemoryTypeFlags, in uint SemanticFlags); void [[]] Barrier(in NodeRecordOrUAV o, in uint SemanticFlags); -uint [[]] GetRemainingRecursionLevels(); +uint [[min_sm=6.8,max_sm=6.9]] GetRemainingRecursionLevels(); // LinAlg intrinsics diff --git a/utils/hct/hctdb.py b/utils/hct/hctdb.py index 90bc1e5de4..5110cb1e71 100644 --- a/utils/hct/hctdb.py +++ b/utils/hct/hctdb.py @@ -9389,6 +9389,7 @@ def __init__( overload_idx, hidden, min_shader_model, + max_shader_model, static_member, class_prefix, ): @@ -9437,6 +9438,12 @@ def __init__( self.min_shader_model = (min_shader_model[0] << 4) | ( min_shader_model[1] & 0x0F ) + # Encoded maximum shader model for this intrinsic, 0 = no maximum + self.max_shader_model = 0 + if max_shader_model: + self.max_shader_model = (max_shader_model[0] << 4) | ( + max_shader_model[1] & 0x0F + ) self.static_member = static_member # HLSL static member function self.key = ( ("%3d" % ns_idx) @@ -9841,6 +9848,7 @@ def process_attr(attr): ) # Parameter determines the overload type, -1 means ret type. hidden = False min_shader_model = (0, 0) + max_shader_model = (0, 0) for a in attrs: if a == "": continue @@ -9897,6 +9905,24 @@ def process_attr(attr): except ValueError: assert False, "invalid min_sm: %s" % (v) continue + if d == "max_sm": + # max_sm is a string like "6.0" or "6.5" + # Convert to a tuple of integers (major, minor) + try: + major_minor = v.split(".") + if len(major_minor) != 2: + raise ValueError + major, minor = major_minor + major = int(major) + minor = int(minor) + # minor of 15 has special meaning, and larger values + # cannot be encoded in the version DWORD. + if major < 0 or minor < 0 or minor > 14: + raise ValueError + max_shader_model = (major, minor) + except ValueError: + assert False, "invalid max_sm: %s" % (v) + continue assert False, "invalid attr %s" % (a) return ( @@ -9908,6 +9934,7 @@ def process_attr(attr): overload_param_index, hidden, min_shader_model, + max_shader_model, static_member, class_prefix, ) @@ -9958,6 +9985,7 @@ def process_attr(attr): overload_param_index, hidden, min_shader_model, + max_shader_model, static_member, class_prefix, ) = process_attr(attr) @@ -10001,6 +10029,7 @@ def process_attr(attr): overload_param_index, hidden, min_shader_model, + max_shader_model, static_member, class_prefix, ) diff --git a/utils/hct/hctdb_instrhelp.py b/utils/hct/hctdb_instrhelp.py index d7a263a8e1..3980ff9b66 100644 --- a/utils/hct/hctdb_instrhelp.py +++ b/utils/hct/hctdb_instrhelp.py @@ -1138,15 +1138,18 @@ def get_hlsl_intrinsics(): flags = " | ".join(flags) else: flags = "0" - ns_table += " {(UINT)%s::%s, %s, 0x%x, %d, %d, g_%s_Args%s},\n" % ( - opcode_namespace, - i.enum_name, - flags, - i.min_shader_model, - i.overload_param_index, - len(i.params), - last_ns, - arg_idx, + ns_table += ( + " {(UINT)%s::%s, %s, 0x%x, %d, %d, g_%s_Args%s, 0x%x},\n" % ( + opcode_namespace, + i.enum_name, + flags, + i.min_shader_model, + i.overload_param_index, + len(i.params), + last_ns, + arg_idx, + i.max_shader_model, + ) ) result += "static const HLSL_INTRINSIC_ARGUMENT g_%s_Args%s[] =\n{\n" % ( last_ns, From a45e39f7bfaaa3cd2981257edcbf5d708ae818b5 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Tue, 18 Aug 2026 14:41:52 -0500 Subject: [PATCH 2/3] clang-format --- include/dxc/dxcapi.internal.h | 4 +-- .../clang/Basic/DiagnosticSemaKinds.td | 35 ++++++++++++------- tools/clang/lib/AST/ASTContextHLSL.cpp | 14 ++++---- tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp | 4 +-- tools/clang/unittests/HLSL/ExtensionTest.cpp | 24 ++++++------- 5 files changed, 46 insertions(+), 35 deletions(-) diff --git a/include/dxc/dxcapi.internal.h b/include/dxc/dxcapi.internal.h index 4264f3f4f6..eeef0aa20a 100644 --- a/include/dxc/dxcapi.internal.h +++ b/include/dxc/dxcapi.internal.h @@ -201,8 +201,8 @@ struct HLSL_INTRINSIC { // type UINT uNumArgs; // Count of arguments in pArgs. const HLSL_INTRINSIC_ARGUMENT *pArgs; // Pointer to first argument. - UINT MaxShaderModel; // Encoded maximum shader model, 0 = no maximum - // (Major << 4) + (Minor & 0xf) + UINT MaxShaderModel; // Encoded maximum shader model, 0 = no maximum + // (Major << 4) + (Minor & 0xf) }; /////////////////////////////////////////////////////////////////////////////// diff --git a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index bca27c7dcd..ab7e1dd476 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7682,18 +7682,29 @@ def warn_hlsl_builtin_constant_unavailable: Warning< def warn_hlsl_builtin_type_unavailable: Warning< "potential misuse of built-in type %0 in shader model %1; introduced" " in shader model %2">, DefaultError, InGroup; -def warn_hlsl_builtin_constant_removed: Warning< - "built-in constant %0 is unavailable in shader model %1; it was removed" - " in shader model %2">, InGroup; -def warn_hlsl_builtin_type_removed: Warning< - "built-in type %0 is unavailable in shader model %1; it was removed" - " in shader model %2">, DefaultError, InGroup; -def warn_hlsl_intrinsic_removed: Warning< - "intrinsic %0 potentially used by '%1' is unavailable; it was removed" - " in shader model %2">, DefaultError, InGroup; -def warn_hlsl_node_shader_removed: Warning< - "node shaders and other Work Graphs functionality are not supported" - " when targeting shader model %0">, DefaultError, InGroup; +def warn_hlsl_builtin_constant_removed + : Warning<"built-in constant %0 is unavailable in shader model %1; it was " + "removed" + " in shader model %2">, + InGroup; +def warn_hlsl_builtin_type_removed + : Warning< + "built-in type %0 is unavailable in shader model %1; it was removed" + " in shader model %2">, + DefaultError, + InGroup; +def warn_hlsl_intrinsic_removed + : Warning< + "intrinsic %0 potentially used by '%1' is unavailable; it was removed" + " in shader model %2">, + DefaultError, + InGroup; +def warn_hlsl_node_shader_removed + : Warning< + "node shaders and other Work Graphs functionality are not supported" + " when targeting shader model %0">, + DefaultError, + InGroup; def err_hlsl_unsupported_char_literal : Error< "unsupported style of char literal - use a single-character char-based literal">; def err_hlsl_unsupported_clipplane_argument_expression : Error< diff --git a/tools/clang/lib/AST/ASTContextHLSL.cpp b/tools/clang/lib/AST/ASTContextHLSL.cpp index 1898aae7e7..5103b067d1 100644 --- a/tools/clang/lib/AST/ASTContextHLSL.cpp +++ b/tools/clang/lib/AST/ASTContextHLSL.cpp @@ -472,10 +472,11 @@ static void AddRecordSubscriptAccess(clang::ASTContext &Ctx, AddRecordAccessMethod(Ctx, RD, ReturnTy, false, true, true); } -AvailabilityAttr *ConstructAvailabilityAttribute( - clang::ASTContext &context, VersionTuple Introduced, - VersionTuple Deprecated = VersionTuple(), - VersionTuple Obsoleted = VersionTuple()) { +AvailabilityAttr * +ConstructAvailabilityAttribute(clang::ASTContext &context, + VersionTuple Introduced, + VersionTuple Deprecated = VersionTuple(), + VersionTuple Obsoleted = VersionTuple()) { AvailabilityAttr *AAttr = AvailabilityAttr::CreateImplicit( context, &context.Idents.get(""), Introduced, Deprecated, Obsoleted, false, ""); @@ -486,9 +487,8 @@ AvailabilityAttr *ConstructAvailabilityAttribute( // obsoleted SM6.10. static AvailabilityAttr * ConstructNodeRecordAvailabilityAttribute(clang::ASTContext &context) { - return ConstructAvailabilityAttribute(context, VersionTuple(6, 8), - VersionTuple(6, 9), - VersionTuple(6, 10)); + return ConstructAvailabilityAttribute( + context, VersionTuple(6, 8), VersionTuple(6, 9), VersionTuple(6, 10)); } /// Adds up-front support for HLSL *NodeOutputRecords template diff --git a/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp b/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp index 0ceed11c72..32cb4e565c 100644 --- a/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp +++ b/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp @@ -797,8 +797,8 @@ void hlsl::DiagnoseTranslationUnit(clang::Sema *self) { // Work Graphs (node shaders) were obsoleted in shader model 6.10. // Declaring a node shader when targeting 6.10 or above is an error, // regardless of whether any node record types are actually used. - if (EntrySK == DXIL::ShaderKind::Node && - shaderModel->IsSMAtLeast(6, 10) && !IsTargetProfileLib6x(*self)) { + if (EntrySK == DXIL::ShaderKind::Node && shaderModel->IsSMAtLeast(6, 10) && + !IsTargetProfileLib6x(*self)) { self->Diag(FDecl->getLocation(), diag::warn_hlsl_node_shader_removed) << shaderModel->GetName(); } diff --git a/tools/clang/unittests/HLSL/ExtensionTest.cpp b/tools/clang/unittests/HLSL/ExtensionTest.cpp index b32644110b..9f55061ca7 100644 --- a/tools/clang/unittests/HLSL/ExtensionTest.cpp +++ b/tools/clang/unittests/HLSL/ExtensionTest.cpp @@ -204,11 +204,11 @@ Intrinsic Intrinsics[] = { {L"test_fn", DEFAULT_NAME, "r", - {1, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnArgs), TestFnArgs, 0}}, + {1, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnArgs), TestFnArgs, 0}}, {L"test_proc", DEFAULT_NAME, "r", - {2, 0, 0, -1, countof(TestProcArgs), TestProcArgs, 0}}, + {2, 0, 0, -1, countof(TestProcArgs), TestProcArgs, 0}}, {L"test_poly", "test_poly.$o", "r", @@ -217,8 +217,8 @@ Intrinsic Intrinsics[] = { {L"test_int", "test_int", "r", - {4, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnIntArgs), TestFnIntArgs, - 0}}, + {4, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnIntArgs), TestFnIntArgs, + 0}}, {L"test_nolower", "test_nolower.$o", "n", @@ -227,27 +227,27 @@ Intrinsic Intrinsics[] = { {L"test_pack_0", "test_pack_0.$o", "p", - {6, 0, 0, -1, countof(TestFnPack0), TestFnPack0, 0}}, + {6, 0, 0, -1, countof(TestFnPack0), TestFnPack0, 0}}, {L"test_pack_1", "test_pack_1.$o", "p", - {7, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack1), TestFnPack1, 0}}, + {7, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack1), TestFnPack1, 0}}, {L"test_pack_2", "test_pack_2.$o", "p", - {8, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack2), TestFnPack2, 0}}, + {8, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack2), TestFnPack2, 0}}, {L"test_pack_3", "test_pack_3.$o", "p", - {9, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack3), TestFnPack3, 0}}, + {9, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestFnPack3), TestFnPack3, 0}}, {L"test_pack_4", "test_pack_4.$o", "p", - {10, 0, 0, -1, countof(TestFnPack4), TestFnPack4, 0}}, + {10, 0, 0, -1, countof(TestFnPack4), TestFnPack4, 0}}, {L"test_rand", "test_rand", "r", - {11, 0, 0, -1, countof(TestRand), TestRand, 0}}, + {11, 0, 0, -1, countof(TestRand), TestRand, 0}}, {L"test_isinf", "test_isinf", "d", @@ -312,8 +312,8 @@ Intrinsic BufferIntrinsics[] = { {L"MyBufferOp", "MyBufferOp", "m", - {12, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestMyBufferOp), - TestMyBufferOp, 0}}, + {12, INTRIN_FLAG_READ_NONE, 0, -1, countof(TestMyBufferOp), TestMyBufferOp, + 0}}, }; // Test adding a method to an object that normally has no methods (SamplerState From f2d07bce8df3a813b9e514a10bc4c35d30e8eea5 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Tue, 18 Aug 2026 14:49:39 -0500 Subject: [PATCH 3/3] Address copilot feedback --- tools/clang/lib/AST/ASTContextHLSL.cpp | 2 +- tools/clang/lib/Sema/SemaHLSL.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/clang/lib/AST/ASTContextHLSL.cpp b/tools/clang/lib/AST/ASTContextHLSL.cpp index 5103b067d1..6077177939 100644 --- a/tools/clang/lib/AST/ASTContextHLSL.cpp +++ b/tools/clang/lib/AST/ASTContextHLSL.cpp @@ -472,7 +472,7 @@ static void AddRecordSubscriptAccess(clang::ASTContext &Ctx, AddRecordAccessMethod(Ctx, RD, ReturnTy, false, true, true); } -AvailabilityAttr * +static AvailabilityAttr * ConstructAvailabilityAttribute(clang::ASTContext &context, VersionTuple Introduced, VersionTuple Deprecated = VersionTuple(), diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index e19897e8f7..0491e0346b 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -2107,6 +2107,9 @@ static void AddHLSLIntrinsicAttr(FunctionDecl *FD, ASTContext &context, unsigned Major = pIntrinsic->MaxShaderModel >> 4; unsigned Minor = pIntrinsic->MaxShaderModel & 0xF; Deprecated = clang::VersionTuple(Major, Minor); + DXASSERT( + Minor <= 14, + "I don't know how we should handle this, so let's assert for now."); Obsoleted = clang::VersionTuple(Major, Minor + 1); } FD->addAttr(AvailabilityAttr::CreateImplicit(