diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index 23b0cb51ba..d86d61f386 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -26,6 +26,12 @@ The included licenses apply to the following files: - Fixed validator rejecting LinAlgMatrix type in DXIL [#8441](https://github.com/microsoft/DirectXShaderCompiler/pull/8441) - Fixed float trunc and coord calc errors in ExecTests [#8420](https://github.com/microsoft/DirectXShaderCompiler/pull/8420) - Convert Bias Vector to match the output type [#8394](https://github.com/microsoft/DirectXShaderCompiler/pull/8394) +- Fixed certain types being disallowed in LinAlg intrinsics [#8465](https://github.com/microsoft/DirectXShaderCompiler/pull/8465) + +#### Misc Features +- Support templates with >> instead of > > in 202x [#8453](https://github.com/microsoft/DirectXShaderCompiler/pull/8453) +- Implement `auto` for type deduction [#8452](https://github.com/microsoft/DirectXShaderCompiler/pull/8452) +- Implement `[[nodiscard]]` attribute to warn on unused returns [#8462](https://github.com/microsoft/DirectXShaderCompiler/pull/8462) #### Bug Fixes - Fixed build break on certain platforms [#8307](https://github.com/microsoft/DirectXShaderCompiler/pull/8307) diff --git a/tools/clang/include/clang/AST/Decl.h b/tools/clang/include/clang/AST/Decl.h index 0d7ffe3808..4e9722533c 100644 --- a/tools/clang/include/clang/AST/Decl.h +++ b/tools/clang/include/clang/AST/Decl.h @@ -2079,6 +2079,10 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext, /// operators. bool hasUnusedResultAttr() const; + // HLSL Change Begin - Add support for nodiscard attribute. + Attr *getNoDiscardAttr() const; + // HLSL Change Ends + /// \brief Returns the storage class as written in the source. For the /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { return StorageClass(SClass); } diff --git a/tools/clang/include/clang/Basic/Attr.td b/tools/clang/include/clang/Basic/Attr.td index f220157d52..c3199013ee 100644 --- a/tools/clang/include/clang/Basic/Attr.td +++ b/tools/clang/include/clang/Basic/Attr.td @@ -2470,13 +2470,15 @@ def WarnUnused : InheritableAttr { let Documentation = [Undocumented]; } +// HLSL Change Begin - add C++11 spelling. def WarnUnusedResult : InheritableAttr { - let Spellings = [GCC<"warn_unused_result">, + let Spellings = [CXX11<"", "nodiscard", 2017>, GCC<"warn_unused_result">, CXX11<"clang", "warn_unused_result">]; let Subjects = SubjectList<[ObjCMethod, CXXRecord, FunctionLike], WarnDiag, "ExpectedFunctionMethodOrClass">; let Documentation = [Undocumented]; } +// HLSL Change End - add C++11 spelling. def Weak : InheritableAttr { let Spellings = [GCC<"weak">]; diff --git a/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/tools/clang/include/clang/Basic/DiagnosticParseKinds.td index e328393726..ac4bad2cc2 100644 --- a/tools/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -285,7 +285,8 @@ def warn_cxx98_compat_trailing_return_type : Warning< "trailing return types are incompatible with C++98">, InGroup, DefaultIgnore; def ext_auto_type_specifier : ExtWarn< - "'auto' type specifier is a C++11 extension">, InGroup; + "'auto' type specifier is a %select{C++11|HLSL 202x}0 extension">, + InGroup; def warn_auto_storage_class : Warning< "'auto' storage class specifier is redundant and incompatible with C++11">, InGroup, DefaultIgnore; diff --git a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index c35d14f7b2..1449bae57d 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6368,9 +6368,11 @@ def warn_side_effects_unevaluated_context : Warning< def warn_side_effects_typeid : Warning< "expression with side effects will be evaluated despite being used as an " "operand to 'typeid'">, InGroup; -def warn_unused_result : Warning< - "ignoring return value of function declared with warn_unused_result " - "attribute">, InGroup>; +// HLSL Change Begin - allow attribute spelling to come in. +def warn_unused_result + : Warning<"ignoring return value of function declared with %0 attribute">, + InGroup>; +// HLSL Change End def warn_unused_volatile : Warning< "expression result unused; assign into a variable to force a volatile load">, InGroup>; diff --git a/tools/clang/include/clang/Lex/Token.h b/tools/clang/include/clang/Lex/Token.h index 7cb0118596..42e45bc035 100644 --- a/tools/clang/include/clang/Lex/Token.h +++ b/tools/clang/include/clang/Lex/Token.h @@ -295,7 +295,7 @@ class Token { // HLSL Change Starts bool isHLSLReserved() const { return is(tok::kw___is_signed) || is(tok::kw___declspec) || - is(tok::kw___forceinline) || is(tok::kw_auto) || is(tok::kw_catch) || + is(tok::kw___forceinline) || is(tok::kw_catch) || is(tok::kw_const_cast) || is(tok::kw_delete) || is(tok::kw_dynamic_cast) || is(tok::kw_enum) || is(tok::kw_explicit) || is(tok::kw_friend) || is(tok::kw_goto) || diff --git a/tools/clang/lib/AST/Decl.cpp b/tools/clang/lib/AST/Decl.cpp index 39b3ac768d..4c8c0ae268 100644 --- a/tools/clang/lib/AST/Decl.cpp +++ b/tools/clang/lib/AST/Decl.cpp @@ -2876,14 +2876,30 @@ bool FunctionDecl::hasUnusedResultAttr() const { QualType RetType = getReturnType(); if (RetType->isRecordType()) { const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl(); - const CXXMethodDecl *MD = dyn_cast(this); - if (Ret && Ret->hasAttr() && - !(MD && MD->getCorrespondingMethodInClass(Ret, true))) + // HLSL Change Begin - nodiscard on a type should apply to all methods, even + // if they are not marked nodiscard themselves. This is the C++17 behavior. + if (Ret && Ret->hasAttr()) return true; + // HLSL Change End } return hasAttr(); } +// HLSL Change Begin - support nodiscard attr. +Attr *FunctionDecl::getNoDiscardAttr() const { + QualType RetType = getReturnType(); + if (RetType->isRecordType()) { + const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl(); + const CXXMethodDecl *MD = dyn_cast(this); + if (Ret && Ret->hasAttr() && + (!hasAttr() || + !(MD && (MD->getCorrespondingMethodInClass(Ret, true))))) + return Ret->getAttr(); + } + return getAttr(); +} +// HLSL Change End + /// \brief For an inline function definition in C, or for a gnu_inline function /// in C++, determine whether the definition will be externally visible. /// diff --git a/tools/clang/lib/Headers/hlsl/dx/linalg.h b/tools/clang/lib/Headers/hlsl/dx/linalg.h index e223f2286e..44c1e96c37 100644 --- a/tools/clang/lib/Headers/hlsl/dx/linalg.h +++ b/tools/clang/lib/Headers/hlsl/dx/linalg.h @@ -289,8 +289,9 @@ class Matrix { } template - static typename hlsl::enable_if::value, Matrix>::type - Splat(T Val) { + [[nodiscard]] static + typename hlsl::enable_if::value, Matrix>::type + Splat(T Val) { Matrix Result; __builtin_LinAlg_FillMatrix(Result.__handle, Val); return Result; @@ -652,7 +653,7 @@ OuterProduct(vector VecA, vector VecB) { template typename hlsl::enable_if::value, void>::type -InterlockedAccumulate(RWByteAddressBuffer Res, vector Vec, +InterlockedAccumulate(vector Vec, RWByteAddressBuffer Res, uint StartOffset, uint Align = 64) { __builtin_LinAlg_VectorAccumulateToDescriptor(Vec, Res, StartOffset, Align); } diff --git a/tools/clang/lib/Parse/ParseDecl.cpp b/tools/clang/lib/Parse/ParseDecl.cpp index c91c8940a4..85404a1673 100644 --- a/tools/clang/lib/Parse/ParseDecl.cpp +++ b/tools/clang/lib/Parse/ParseDecl.cpp @@ -3918,8 +3918,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, break; // HLSL Change Ends case tok::kw_auto: - if (getLangOpts().HLSL) { goto HLSLReservedKeyword; } // HLSL Change - auto is reserved for HLSL - if (getLangOpts().CPlusPlus11) { + // HLSL Change Begin - auto is reserved for HLSL 2015 and earlier. + if (getLangOpts().HLSL && + getLangOpts().HLSLVersion <= hlsl::LangStd::v2015) + goto HLSLReservedKeyword; + // HLSL Change End + if (getLangOpts().CPlusPlus11 || getLangOpts().HLSL) { // HLSL Change if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, PrevSpec, DiagID, Policy); diff --git a/tools/clang/lib/Parse/ParseExpr.cpp b/tools/clang/lib/Parse/ParseExpr.cpp index 8f51dd4b6c..9af3dbe610 100644 --- a/tools/clang/lib/Parse/ParseExpr.cpp +++ b/tools/clang/lib/Parse/ParseExpr.cpp @@ -254,9 +254,11 @@ static bool isFoldOperator(tok::TokenKind Kind) { /// precedence of at least \p MinPrec. ExprResult Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { - prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(), - GreaterThanIsOperator, - getLangOpts().CPlusPlus11); + prec::Level NextTokPrec = + getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, + getLangOpts().CPlusPlus11 || + (getLangOpts().HLSL && getLangOpts().HLSLVersion >= + hlsl::LangStd::v202x)); SourceLocation ColonLoc; while (1) { @@ -390,8 +392,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { // Remember the precedence of this operator and get the precedence of the // operator immediately to the right of the RHS. prec::Level ThisPrec = NextTokPrec; - NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, - getLangOpts().CPlusPlus11); + NextTokPrec = getBinOpPrecedence( + Tok.getKind(), GreaterThanIsOperator, + getLangOpts().CPlusPlus11 || + (getLangOpts().HLSL && + getLangOpts().HLSLVersion >= hlsl::LangStd::v202x)); // Assignment and conditional expressions are right-associative. bool isRightAssoc = ThisPrec == prec::Conditional || @@ -424,8 +429,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { LHS = ExprError(); } - NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, - getLangOpts().CPlusPlus11); + NextTokPrec = getBinOpPrecedence( + Tok.getKind(), GreaterThanIsOperator, + getLangOpts().CPlusPlus11 || + (getLangOpts().HLSL && + getLangOpts().HLSLVersion >= hlsl::LangStd::v202x)); } if (!RHS.isInvalid() && RHSIsInitList) { diff --git a/tools/clang/lib/Parse/ParseTemplate.cpp b/tools/clang/lib/Parse/ParseTemplate.cpp index dc334cf7d6..fbedf41caa 100644 --- a/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/tools/clang/lib/Parse/ParseTemplate.cpp @@ -840,7 +840,9 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " "); unsigned DiagId = diag::err_two_right_angle_brackets_need_space; - if (getLangOpts().CPlusPlus11 && + if ((getLangOpts().CPlusPlus11 || + (getLangOpts().HLSL && + getLangOpts().HLSLVersion >= hlsl::LangStd::v202x)) && (Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater))) DiagId = diag::warn_cxx98_compat_two_right_angle_brackets; else if (Tok.is(tok::greaterequal)) diff --git a/tools/clang/lib/Sema/DeclSpec.cpp b/tools/clang/lib/Sema/DeclSpec.cpp index 37c1554092..455f755242 100644 --- a/tools/clang/lib/Sema/DeclSpec.cpp +++ b/tools/clang/lib/Sema/DeclSpec.cpp @@ -1158,8 +1158,14 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli } // Diagnose if we've recovered from an ill-formed 'auto' storage class // specifier in a pre-C++11 dialect of C++. - if (!PP.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto) - Diag(D, TSTLoc, diag::ext_auto_type_specifier); + // HLSL Change Begin - HLSL supports 'auto' as a type specifier in 202x+. + if (!(PP.getLangOpts().CPlusPlus11 || + (PP.getLangOpts().HLSL && + PP.getLangOpts().HLSLVersion >= hlsl::LangStd::v202x)) && + TypeSpecType == TST_auto) + Diag(D, TSTLoc, diag::ext_auto_type_specifier) + << /* HLSL */ PP.getLangOpts().HLSL; + // HLSL Change End if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus11 && StorageClassSpec == SCS_auto) Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class) diff --git a/tools/clang/lib/Sema/SemaDecl.cpp b/tools/clang/lib/Sema/SemaDecl.cpp index a772054960..b6fb971aac 100644 --- a/tools/clang/lib/Sema/SemaDecl.cpp +++ b/tools/clang/lib/Sema/SemaDecl.cpp @@ -9047,7 +9047,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. - assert(!getLangOpts().HLSL && "auto types are not supported - merge type below is inconsequential"); // HLSL Change if (VarDecl *Old = VDecl->getPreviousDecl()) { // We never need to merge the type, because we cannot form an incomplete // array of auto, nor deduce such a type. diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 127733e71e..2067ebaf26 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -1170,12 +1170,14 @@ static const ArBasicKind g_RayQueryCT[] = {AR_OBJECT_RAY_QUERY, AR_BASIC_UNKNOWN}; static const ArBasicKind g_LinAlgCT[] = { + AR_BASIC_LITERAL_FLOAT, AR_BASIC_FLOAT16, AR_BASIC_FLOAT32, AR_BASIC_FLOAT32_PARTIAL_PRECISION, - AR_BASIC_FLOAT16, AR_BASIC_INT32, - AR_BASIC_INT16, AR_BASIC_UINT32, - AR_BASIC_UINT16, AR_BASIC_INT8_4PACKED, - AR_BASIC_UINT8_4PACKED, AR_BASIC_NOCAST, - AR_BASIC_UNKNOWN}; + AR_BASIC_FLOAT64, AR_BASIC_LITERAL_INT, + AR_BASIC_UINT16, AR_BASIC_UINT32, + AR_BASIC_UINT64, AR_BASIC_INT16, + AR_BASIC_INT32, AR_BASIC_INT64, + AR_BASIC_UINT8_4PACKED, AR_BASIC_INT8_4PACKED, + AR_BASIC_NOCAST, AR_BASIC_UNKNOWN}; static const ArBasicKind g_AccelerationStructCT[] = { AR_OBJECT_ACCELERATION_STRUCT, AR_BASIC_UNKNOWN}; diff --git a/tools/clang/lib/Sema/SemaStmt.cpp b/tools/clang/lib/Sema/SemaStmt.cpp index 4e47a68888..baa9559dbb 100644 --- a/tools/clang/lib/Sema/SemaStmt.cpp +++ b/tools/clang/lib/Sema/SemaStmt.cpp @@ -245,7 +245,11 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { const FunctionDecl *Func = dyn_cast(FD); if (Func ? Func->hasUnusedResultAttr() : FD->hasAttr()) { - Diag(Loc, diag::warn_unused_result) << R1 << R2; + // HLSL Change Begin - allow attribute spelling to come in. + Attr *NoDiscardAttr = Func ? Func->getNoDiscardAttr() + : FD->getAttr(); + Diag(Loc, diag::warn_unused_result) << NoDiscardAttr << R1 << R2; + // HLSL Change End return; } if (ShouldSuppress) @@ -270,7 +274,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { const ObjCMethodDecl *MD = ME->getMethodDecl(); if (MD) { if (MD->hasAttr()) { - Diag(Loc, diag::warn_unused_result) << R1 << R2; + // HLSL Change Begin - allow attribute spelling to come in. + Diag(Loc, diag::warn_unused_result) + << MD->getAttr() << R1 << R2; + // HLSL Change End return; } } diff --git a/tools/clang/test/CodeGenDXIL/hlsl/linalg/api/vectors.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/linalg/api/vectors.hlsl index 3d1735aa9c..b449a29635 100644 --- a/tools/clang/test/CodeGenDXIL/hlsl/linalg/api/vectors.hlsl +++ b/tools/clang/test/CodeGenDXIL/hlsl/linalg/api/vectors.hlsl @@ -193,9 +193,9 @@ void main(uint ID : SV_GroupID) { // CHECK: call void @dx.op.linAlgVectorAccumulateToDescriptor.v4f16(i32 -2147483617, <4 x half> // CHECK-SAME: , %dx.types.Handle %{{[0-9]+}}, i32 0, i32 64) // CHECK-SAME: ; LinAlgVectorAccumulateToDescriptor(vector,handle,offset,align) - InterlockedAccumulate(RWBAB, vec1, 0); + InterlockedAccumulate(vec1, RWBAB, 0); // CHECK: call void @dx.op.linAlgVectorAccumulateToDescriptor.v8f16(i32 -2147483617, <8 x half> %{{[0-9]+}}, // CHECK-SAME: %dx.types.Handle %{{[0-9]+}}, i32 8, i32 64) ; LinAlgVectorAccumulateToDescriptor(vector,handle,offset,align) - InterlockedAccumulate(RWBAB, vec2, 8); + InterlockedAccumulate(vec2, RWBAB, 8); } diff --git a/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixvectormultiplyadd/nominal.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixvectormultiplyadd/nominal.hlsl index d4f0037460..edfa306148 100644 --- a/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixvectormultiplyadd/nominal.hlsl +++ b/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixvectormultiplyadd/nominal.hlsl @@ -49,4 +49,18 @@ void main() { // CHECK2-SAME: i1 true, <4 x i64> %{{[0-9]+}}, i32 1, <4 x i64> %{{[0-9]+}}, i32 0) __builtin_LinAlg_MatrixVectorMultiplyAdd(result3, mat3, true, vec3, 1, result3, 0); + + // CHECK: call <8 x i32> @dx.op.linAlgMatVecMulAdd.v8i32.mC17M8N8U0S0.v8i32.v8i32(i32 -2147483622, + // CHECK-SAME: %dx.types.LinAlgMatrixC17M8N8U0S0 {{.*}}, i1 true, <8 x i32> zeroinitializer, + // CHECK-SAME: i32 1, <8 x i32> zeroinitializer, i32 0) + // CHECK-SAME: ; LinAlgMatVecMulAdd(matrix,isOutputSigned,inputVector,inputInterpretation,biasVector,biasInterpretation) + + // CHECK2: call void @"dx.hl.op..void (i32, <8 x i32>*, %dx.types.LinAlgMatrixC17M8N8U0S0, i1, <8 x i32>, + // CHECK2-SAME: i32, <8 x i32>, i32)"(i32 419, <8 x i32>* %result4, %dx.types.LinAlgMatrixC17M8N8U0S0 %{{[0-9]+}}, + // CHECK2-SAME: i1 true, <8 x i32> %{{[0-9]+}}, i32 1, <8 x i32> %{{[0-9]+}}, i32 0) + + __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(17, 8, 8, 0, 0)]] mat4; + vector vec4 = 0; + vector result4 = 0; + __builtin_LinAlg_MatrixVectorMultiplyAdd(result4, mat4, true, vec4, 1, result4, 0); } diff --git a/tools/clang/test/CodeGenSPIRV/var.auto.deduction.hlsl b/tools/clang/test/CodeGenSPIRV/var.auto.deduction.hlsl new file mode 100644 index 0000000000..553bb6642a --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/var.auto.deduction.hlsl @@ -0,0 +1,51 @@ +// RUN: %dxc -T cs_6_0 -E main -HV 202x -fcgl %s -spirv | FileCheck %s + +// Test that the 'auto' keyword can be used to declare variables with inferred +// types from initialization expressions when targeting SPIR-V. + +// CHECK: [[INT:%[a-zA-Z0-9_]+]] = OpTypeInt 32 1 +// CHECK: [[INT_1:%[a-zA-Z0-9_]+]] = OpConstant [[INT]] 1 +// CHECK: [[FLOAT:%[a-zA-Z0-9_]+]] = OpTypeFloat 32 +// CHECK: [[FLOAT_2:%[a-zA-Z0-9_]+]] = OpConstant [[FLOAT]] 2 +// CHECK: [[BOOL:%[a-zA-Z0-9_]+]] = OpTypeBool +// CHECK: [[TRUE:%[a-zA-Z0-9_]+]] = OpConstantTrue [[BOOL]] +// CHECK: [[V4FLOAT:%[a-zA-Z0-9_]+]] = OpTypeVector [[FLOAT]] 4 +// CHECK: [[VEC_CONST:%[a-zA-Z0-9_]+]] = OpConstantComposite [[V4FLOAT]] {{%[a-zA-Z0-9_]+}} [[FLOAT_2]] {{%[a-zA-Z0-9_]+}} {{%[a-zA-Z0-9_]+}} + +// CHECK: [[PTR_INT:%_ptr_Function_int]] = OpTypePointer Function [[INT]] +// CHECK: [[PTR_FLOAT:%_ptr_Function_float]] = OpTypePointer Function [[FLOAT]] +// CHECK: [[PTR_BOOL:%_ptr_Function_bool]] = OpTypePointer Function [[BOOL]] +// CHECK: [[PTR_V4FLOAT:%_ptr_Function_v4float]] = OpTypePointer Function [[V4FLOAT]] + +// CHECK: %a = OpVariable [[PTR_INT]] Function +// CHECK: %b = OpVariable [[PTR_FLOAT]] Function +// CHECK: %c = OpVariable [[PTR_BOOL]] Function +// CHECK: %d = OpVariable [[PTR_V4FLOAT]] Function +// CHECK: %sum = OpVariable [[PTR_INT]] Function +// CHECK: %product = OpVariable [[PTR_FLOAT]] Function + +// CHECK: OpStore %a [[INT_1]] +// CHECK: OpStore %b [[FLOAT_2]] +// CHECK: OpStore %c [[TRUE]] +// CHECK: OpStore %d [[VEC_CONST]] + +RWBuffer output : register(u0); + +[numthreads(1,1,1)] +void main() { + // Auto deduces int from integer literal + auto a = 1; + // Auto deduces float from float literal + auto b = 2.0f; + // Auto deduces bool from bool literal + auto c = true; + // Auto deduces float4 from vector type + auto d = float4(1.0f, 2.0f, 3.0f, 4.0f); + + // Auto from arithmetic expressions + auto sum = a + a; + auto product = b * b; + + // Use the values to prevent dead-code elimination + output[0] = (float)sum + product + d.x + (float)c; +} diff --git a/tools/clang/test/CodeGenSPIRV/var.auto.template.hlsl b/tools/clang/test/CodeGenSPIRV/var.auto.template.hlsl new file mode 100644 index 0000000000..7a2b5acf4d --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/var.auto.template.hlsl @@ -0,0 +1,53 @@ +// RUN: %dxc -T cs_6_0 -E main -HV 202x -fcgl %s -spirv | FileCheck %s + +// Test that the 'auto' keyword works correctly in template contexts when +// targeting SPIR-V: +// - auto variables inside template function bodies +// - auto variables assigned from results of template function instantiations + +RWBuffer output : register(u0); + +// Template with explicit return type; auto is used inside the body. +template +T square(T val) { + auto result = val * val; + return result; +} + +// Template with explicit return type using a conditional expression. +template +T clampPositive(T val) { + auto zero = (T)0; + auto clamped = val < zero ? zero : val; + return clamped; +} + +// CHECK: [[INT:%[a-zA-Z0-9_]+]] = OpTypeInt 32 1 +// CHECK: [[FLOAT:%[a-zA-Z0-9_]+]] = OpTypeFloat 32 +// CHECK: [[PTR_INT:%_ptr_Function_int]] = OpTypePointer Function [[INT]] +// CHECK: [[PTR_FLOAT:%_ptr_Function_float]] = OpTypePointer Function [[FLOAT]] + +// Auto-deduced locals in main() instantiated for int and float. +// CHECK: %a = OpVariable [[PTR_INT]] Function +// CHECK: %b = OpVariable [[PTR_FLOAT]] Function +// CHECK: %c = OpVariable [[PTR_INT]] Function +// CHECK: %d = OpVariable [[PTR_FLOAT]] Function + +// Auto inside template bodies retains correct types after instantiation. +// CHECK: %result = OpVariable [[PTR_INT]] Function +// CHECK: %result_0 = OpVariable [[PTR_FLOAT]] Function +// CHECK: %zero = OpVariable [[PTR_INT]] Function +// CHECK: %clamped = OpVariable [[PTR_INT]] Function +// CHECK: %zero_0 = OpVariable [[PTR_FLOAT]] Function +// CHECK: %clamped_0 = OpVariable [[PTR_FLOAT]] Function + +[numthreads(1,1,1)] +void main() { + // auto variables assigned from template instantiation results. + auto a = square(5); // instantiated as int + auto b = square(2.5f); // instantiated as float + auto c = clampPositive(-3); // instantiated as int + auto d = clampPositive(1.5f); // instantiated as float + + output[0] = (float)a + b + (float)c + d; +} diff --git a/tools/clang/test/HLSL/cpp-errors.hlsl b/tools/clang/test/HLSL/cpp-errors.hlsl index bee34d249b..1ecf4a57e1 100644 --- a/tools/clang/test/HLSL/cpp-errors.hlsl +++ b/tools/clang/test/HLSL/cpp-errors.hlsl @@ -12,7 +12,7 @@ s_arr_i_f arr_struct_two[] = { 1, 2, 3, 4 }; int g_int; typeof(g_int) g_typeof_int; // expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{expected ';' after top level declarator}} expected-error {{unknown type name 'typeof'; did you mean 'typedef'?}} typedef int (*fn_int)(int); // expected-error {{pointers are unsupported in HLSL}} -auto g_auto = 3; // expected-error {{'auto' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}} +auto g_auto = 3; // auto is now supported in HLSL via type deduction; no error expected __is_signed g_is_signed; // expected-error {{'__is_signed' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}} register int g_register; // expected-error {{'register' is a reserved keyword in HLSL}} __thread int g_thread; // expected-error {{'__thread' is a reserved keyword in HLSL}} @@ -65,7 +65,8 @@ void fn_throw() throw() { } // expected-error {{exception specification is unsup void fn_noexcept() noexcept { }; // expected-error {{expected function body after function declarator}} // This would be a failure because of unsupported trailer return types, but we mis-parse it differently. -auto fn_trailing() -> int { return 1; } ; // expected-error {{'auto' is a reserved keyword in HLSL}} expected-error {{expected function body after function declarator}} +// auto is now type-deduced so no reserved keyword error; only the trailing return type syntax causes an error. +auto fn_trailing() -> int { return 1; } ; // expected-error {{expected function body after function declarator}} void fn_param_with_default(int val = 1) { } void fn_with_variadic(int a, ...) { } // expected-error {{variadic arguments is unsupported in HLSL}} diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-pointer.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-pointer.hlsl new file mode 100644 index 0000000000..425a69cd8c --- /dev/null +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-pointer.hlsl @@ -0,0 +1,10 @@ +// RUN: %dxc -T cs_6_0 -HV 202x -verify %s + +// Test that 'auto' cannot be used to declare pointer types in HLSL. +// Pointers are unsupported in HLSL. + +[numthreads(1,1,1)] +void main() { + int x = 1; + auto* ptr = &x; // expected-error {{pointers are unsupported in HLSL}} +} diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-reference.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-reference.hlsl new file mode 100644 index 0000000000..499c26aec7 --- /dev/null +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-reference.hlsl @@ -0,0 +1,11 @@ +// RUN: %dxc -T cs_6_0 -HV 202x -verify %s + +// Test that 'auto' cannot be used to declare reference types in HLSL. +// References are unsupported in HLSL. + +int gVal = 42; + +[numthreads(1,1,1)] +void main() { + auto& ref = gVal; // expected-error {{references are unsupported in HLSL}} +} diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-template.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-template.hlsl new file mode 100644 index 0000000000..885d2226ae --- /dev/null +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-template.hlsl @@ -0,0 +1,41 @@ +// RUN: %dxc -T cs_6_0 -HV 202x -fcgl %s | FileCheck %s + +// Test that the 'auto' keyword works correctly in template contexts in HLSL: +// - auto variables inside template function bodies +// - auto variables assigned from results of template function instantiations + + + +RWBuffer output : register(u0); + +// Template with explicit return type; auto is used inside the body. +template +T square(T val) { + auto result = val * val; + return result; +} + +// Template with explicit return type using a conditional expression. +template +T clampPositive(T val) { + auto zero = (T)0; + auto clamped = val < zero ? zero : val; + return clamped; +} + +// CHECK-LABEL: define void @main() +// CHECK: {{.*}} = alloca i32 +// CHECK: {{.*}} = alloca float +// CHECK: {{.*}} = alloca i32 +// CHECK: {{.*}} = alloca float + +[numthreads(1,1,1)] +void main() { + // auto variables assigned from template instantiation results. + auto a = square(5); // instantiated as int + auto b = square(2.5f); // instantiated as float + auto c = clampPositive(-3); // instantiated as int, result = 0 + auto d = clampPositive(1.5f); // instantiated as float + + output[0] = (float)a + b + (float)c + d; +} diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-variable-deduction.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-variable-deduction.hlsl new file mode 100644 index 0000000000..8cc375a02e --- /dev/null +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-variable-deduction.hlsl @@ -0,0 +1,55 @@ +// RUN: %dxc -T cs_6_0 -E main - %s -verify +// RUN: %dxc -T cs_6_0 -E main -HV 202x -fcgl %s | FileCheck %s + +// Test that the 'auto' keyword can be used to declare variables with inferred +// types from initialization expressions in HLSL. + +// CHECK-LABEL: define void @main() +// CHECK: [[A:%[a-zA-Z0-9_]+]] = alloca i32 +// CHECK: [[B:%[a-zA-Z0-9_]+]] = alloca float +// CHECK: [[C:%[a-zA-Z0-9_]+]] = alloca i32 +// CHECK: [[D:%[a-zA-Z0-9_]+]] = alloca <4 x float> +// CHECK: {{.*}} = alloca i32 +// CHECK: {{.*}} = alloca float +// CHECK: {{.*}} = alloca <4 x float> +// CHECK: {{.*}} = alloca i32 +// CHECK: {{.*}} = alloca float +// CHECK: store i32 1, i32* [[A]] +// CHECK: store float 2.000000e+00, float* [[B]] +// CHECK: store i32 1, i32* [[C]] + +RWBuffer output : register(u0); + +[numthreads(1,1,1)] +void main() { + // Auto deduces int from integer literal + // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} + auto a = 1; + // Auto deduces float from float literal + // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} + auto b = 2.0f; + // Auto deduces bool (stored as i32) from bool literal + // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} + auto c = true; + // Auto deduces float4 from vector type + // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} + auto d = float4(1.0f, 2.0f, 3.0f, 4.0f); + + // Auto from arithmetic expressions + // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} + auto sum = a + a; + // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} + auto product = b * b; + + // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} + auto mulAdd = mad(d, d, d); + + // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} + auto m = min(sum, c); + + // expected-warning@+1 {{'auto' type specifier is a HLSL 202x extension}} + auto dP = dot(d, d); + + // Use the values to prevent dead-code elimination + output[0] = (float)sum + product + d.x + (float)c; +} diff --git a/tools/clang/test/SemaHLSL/attributes/nodiscard.hlsl b/tools/clang/test/SemaHLSL/attributes/nodiscard.hlsl new file mode 100644 index 0000000000..c925b5ba42 --- /dev/null +++ b/tools/clang/test/SemaHLSL/attributes/nodiscard.hlsl @@ -0,0 +1,36 @@ +// RUN: %dxc -I %hlsl_headers -T cs_6_10 -verify %s + +#include +using namespace dx::linalg; + +using MatrixATy = Matrix; + +[nodiscard] int fn() { return 42; } +[[nodiscard]] int fn2() { return 42; } + +struct [[nodiscard]] S { + int x; + + [[clang::warn_unused_result]] static S fn4() { return (S)42; } + [[clang::warn_unused_result]] S fn5() { return (S)42; } + + static S fn6() { return (S)42; } + S fn7() { return (S)42; } +}; + +S fn3() { return (S)42; } + +[numthreads(4, 4, 4)] +void main(uint ID : SV_GroupID) +{ + MatrixATy MatA1; + MatA1.Splat(1.0f); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + fn(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + fn2(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + fn3(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + S::fn4(); // expected-warning {{ignoring return value of function declared with 'warn_unused_result' attribute}} + S s; + s.fn5(); // expected-warning {{ignoring return value of function declared with 'warn_unused_result' attribute}} + S::fn6(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + s.fn7(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} +} diff --git a/tools/clang/test/SemaHLSL/v2021/templates/template-right-angle-brackets.hlsl b/tools/clang/test/SemaHLSL/v2021/templates/template-right-angle-brackets.hlsl new file mode 100644 index 0000000000..4db25fabc0 --- /dev/null +++ b/tools/clang/test/SemaHLSL/v2021/templates/template-right-angle-brackets.hlsl @@ -0,0 +1,31 @@ +// RUN: %dxc -T lib_6_3 -HV 2021 -verify %s + +// In HLSL 2021, two consecutive right angle brackets (>>) in a template +// argument list must be separated by a space. Using >> without spaces should +// produce an error. + +template +struct Outer { T val; }; + +template +struct Inner { T val; }; + +// Nested template type using >> without space: should be an error in HLSL 2021. +Outer> g_nested; // expected-error {{a space is required between consecutive right angle brackets (use '> >')}} + +template +struct Wrapper { + Outer> field; // expected-error {{a space is required between consecutive right angle brackets (use '> >')}} +}; + +// Function return type with nested template and >>. +Outer> getVal(); // expected-error {{a space is required between consecutive right angle brackets (use '> >')}} + +// Function parameter with nested template and >>. +void takeVal(Outer> v); // expected-error {{a space is required between consecutive right angle brackets (use '> >')}} + +// Three right angle brackets (>>>) in a template should also error. +template +struct Pair { T first; U second; }; + +Outer>> g_triple; // expected-error {{a space is required between consecutive right angle brackets (use '> >')}} diff --git a/tools/clang/test/SemaHLSL/v202x/templates/template-right-angle-brackets.hlsl b/tools/clang/test/SemaHLSL/v202x/templates/template-right-angle-brackets.hlsl new file mode 100644 index 0000000000..10790e9433 --- /dev/null +++ b/tools/clang/test/SemaHLSL/v202x/templates/template-right-angle-brackets.hlsl @@ -0,0 +1,39 @@ +// RUN: %dxc -T lib_6_3 -HV 202x -verify %s +// RUN: %dxc -T lib_6_3 -HV 202x -ast-dump %s 2>&1 | FileCheck %s + +// In HLSL 202x, two consecutive right angle brackets (>>) are allowed in +// template argument lists without spaces, matching C++11 behavior. No +// diagnostic should be emitted for >> or >>> in this mode. + +// expected-no-diagnostics + +template +struct Outer { T val; }; + +template +struct Inner { T val; }; + +// Nested template type using >> without space: no error in HLSL 202x. +// CHECK: VarDecl {{.*}} g_nested 'Outer >' +Outer> g_nested; + +template +struct Wrapper { + // CHECK: FieldDecl {{.*}} field 'Outer >' + Outer> field; +}; + +// Function return type with nested template using >>. +// CHECK: FunctionDecl {{.*}} getVal 'Outer > ()' +Outer> getVal(); + +// Function parameter using >>. +// CHECK: FunctionDecl {{.*}} takeVal 'void (Outer >)' +void takeVal(Outer> v); + +// Three right angle brackets (>>>) in a template: no error in HLSL 202x. +template +struct Pair { T first; U second; }; + +// CHECK: VarDecl {{.*}} g_triple 'Outer > >' +Outer>> g_triple; diff --git a/tools/clang/unittests/HLSLExec/LinAlgTests.cpp b/tools/clang/unittests/HLSLExec/LinAlgTests.cpp index 7b8aeeeba7..b3c4b761ea 100644 --- a/tools/clang/unittests/HLSLExec/LinAlgTests.cpp +++ b/tools/clang/unittests/HLSLExec/LinAlgTests.cpp @@ -359,6 +359,9 @@ class DxilConf_SM610_LinAlg { // Convert TEST_METHOD(Convert); + // Vector Accumulate + TEST_METHOD(VectorAccumulateDescriptor_Thread_F16); + private: CComPtr D3DDevice; dxc::SpecificDllLoader DxcSupport; @@ -1693,7 +1696,7 @@ static const char ConvertShader[] = R"( static void runConvert(ID3D12Device *Device, dxc::SpecificDllLoader &DxcSupport, bool Verbose) { - std::string Args = "-HV 202x"; + std::string Args = "-HV 202x -enable-16bit-types"; MatrixDim NumElements = 4; size_t BufferSize = elementSize(ComponentType::F32) * NumElements; @@ -1718,4 +1721,44 @@ void DxilConf_SM610_LinAlg::Convert() { runConvert(D3DDevice, DxcSupport, VerboseLogging); } +static const char VectorAccumulateDescriptorShader[] = R"( + RWByteAddressBuffer Output : register(u0); + + [numthreads(1, 1, 1)] + void main() { + vector InVec = {1.0, 2.0, 3.0, 4.0}; + __builtin_LinAlg_VectorAccumulateToDescriptor(InVec, Output, 0, 64); + } +)"; + +static void runVectorAccumulateDescriptor(ID3D12Device *Device, + dxc::SpecificDllLoader &DxcSupport, + bool Verbose) { + std::string Args = "-HV 202x -enable-16bit-types"; + MatrixDim NumElements = 4; + size_t BufferSize = elementSize(ComponentType::F16) * NumElements; + + compileShader(DxcSupport, VectorAccumulateDescriptorShader, "cs_6_10", Args, + Verbose); + + auto Expected = makeExpectedVec(ComponentType::F16, NumElements, 1.0); + + auto Op = createComputeOp(VectorAccumulateDescriptorShader, "cs_6_10", + "UAV(u0)", Args.c_str()); + addUAVBuffer(Op.get(), "Output", BufferSize, true); + addRootView(Op.get(), 0, "Output"); + + auto Result = runShaderOp(Device, DxcSupport, std::move(Op)); + + MappedData OutData; + Result->Test->GetReadBackData("Output", &OutData); + + VERIFY_IS_TRUE(verifyComponentBuffer(ComponentType::F16, OutData.data(), + Expected, NumElements, Verbose)); +} + +void DxilConf_SM610_LinAlg::VectorAccumulateDescriptor_Thread_F16() { + runVectorAccumulateDescriptor(D3DDevice, DxcSupport, VerboseLogging); +} + } // namespace LinAlg diff --git a/utils/hct/gen_intrin_main.txt b/utils/hct/gen_intrin_main.txt index c0d1d3dcfc..37a4ee406f 100644 --- a/utils/hct/gen_intrin_main.txt +++ b/utils/hct/gen_intrin_main.txt @@ -393,24 +393,24 @@ void [[min_sm=6.10]] __builtin_LinAlg_FillMatrix(out LinAlgMatrix ret, in numeri void [[min_sm=6.10]] __builtin_LinAlg_CopyConvertMatrix(out LinAlgMatrix ret, in LinAlgMatrix source, in bool transpose); void [[min_sm=6.10]] __builtin_LinAlg_MatrixLoadFromDescriptor(out LinAlgMatrix ret, in ByteAddressBuffer buf, in uint offset, in uint stride, in uint layout, in uint align); void [[min_sm=6.10]] __builtin_LinAlg_MatrixLoadFromDescriptor(out LinAlgMatrix ret, in RWByteAddressBuffer buf, in uint offset, in uint stride, in uint layout, in uint align); -void [[min_sm=6.10]] __builtin_LinAlg_MatrixLoadFromMemory(out LinAlgMatrix ret, groupshared numeric[] memory, in uint offset, in uint stride, in uint layout); +void [[min_sm=6.10]] __builtin_LinAlg_MatrixLoadFromMemory(out LinAlgMatrix ret, groupshared LinAlg[] memory, in uint offset, in uint stride, in uint layout); uint [[min_sm=6.10]] __builtin_LinAlg_MatrixLength(in LinAlgMatrix matrix); uint<2> [[min_sm=6.10]] __builtin_LinAlg_MatrixGetCoordinate(in LinAlgMatrix matrix, in uint threadLocalIndex); -void [[min_sm=6.10]] __builtin_LinAlg_MatrixGetElement(out numeric ret, in LinAlgMatrix matrix, in uint threadLocalIndex); -void [[min_sm=6.10]] __builtin_LinAlg_MatrixSetElement(ref LinAlgMatrix ret, in LinAlgMatrix matrix, in uint threadLocalIndex, in numeric value); +void [[min_sm=6.10]] __builtin_LinAlg_MatrixGetElement(out LinAlg ret, in LinAlgMatrix matrix, in uint threadLocalIndex); +void [[min_sm=6.10]] __builtin_LinAlg_MatrixSetElement(ref LinAlgMatrix ret, in LinAlgMatrix matrix, in uint threadLocalIndex, in LinAlg value); void [[min_sm=6.10]] __builtin_LinAlg_MatrixStoreToDescriptor(in LinAlgMatrix matrix, in RWByteAddressBuffer buf, in uint offset, in uint stride, in uint layout, in uint align); -void [[min_sm=6.10]] __builtin_LinAlg_MatrixStoreToMemory(in LinAlgMatrix matrix, groupshared numeric[] memory, in uint offset, in uint stride, in uint layout); +void [[min_sm=6.10]] __builtin_LinAlg_MatrixStoreToMemory(in LinAlgMatrix matrix, groupshared LinAlg[] memory, in uint offset, in uint stride, in uint layout); uint [[min_sm=6.10]] __builtin_LinAlg_MatrixQueryAccumulatorLayout(); void [[min_sm=6.10]] __builtin_LinAlg_MatrixMatrixMultiply(out LinAlgMatrix matrixC, in LinAlgMatrix matrixA, in LinAlgMatrix matrixB); void [[min_sm=6.10]] __builtin_LinAlg_MatrixMatrixMultiplyAccumulate(ref LinAlgMatrix matrixR, in LinAlgMatrix matrixA, in LinAlgMatrix matrixB, in LinAlgMatrix matrixC); void [[min_sm=6.10]] __builtin_LinAlg_MatrixAccumulate(ref LinAlgMatrix matrixC, in LinAlgMatrix matrixLHS, in LinAlgMatrix matrixRHS); -void [[min_sm=6.10]] __builtin_LinAlg_MatrixVectorMultiply(out numeric ret, in LinAlgMatrix mat, in bool isOutputSigned, in numeric input, in uint inputInterp); -void [[min_sm=6.10]] __builtin_LinAlg_MatrixVectorMultiplyAdd(out numeric ret, in LinAlgMatrix mat, in bool isOutputSigned, in numeric input, in uint inputInterp, in numeric bias, in uint biasInterp); +void [[min_sm=6.10]] __builtin_LinAlg_MatrixVectorMultiply(out LinAlg ret, in LinAlgMatrix mat, in bool isOutputSigned, in LinAlg input, in uint inputInterp); +void [[min_sm=6.10]] __builtin_LinAlg_MatrixVectorMultiplyAdd(out LinAlg ret, in LinAlgMatrix mat, in bool isOutputSigned, in LinAlg input, in uint inputInterp, in LinAlg bias, in uint biasInterp); void [[min_sm=6.10]] __builtin_LinAlg_MatrixAccumulateToDescriptor(in LinAlgMatrix matrix, in RWByteAddressBuffer buf, in uint offset, in uint stride, in uint layout, in uint align); -void [[min_sm=6.10]] __builtin_LinAlg_MatrixAccumulateToMemory(in LinAlgMatrix matrix, groupshared numeric[] memory, in uint offset, in uint stride, in uint layout); -void [[min_sm=6.10]] __builtin_LinAlg_MatrixOuterProduct(out LinAlgMatrix ret, in numeric vecA, in numeric vecB); -void [[min_sm=6.10]] __builtin_LinAlg_Convert(out numeric ret, in numeric vec, in uint input_interp, in uint output_interp); -void [[min_sm=6.10]] __builtin_LinAlg_VectorAccumulateToDescriptor(in numeric<> vec, in RWByteAddressBuffer buf, in uint offset, in uint align); +void [[min_sm=6.10]] __builtin_LinAlg_MatrixAccumulateToMemory(in LinAlgMatrix matrix, groupshared LinAlg[] memory, in uint offset, in uint stride, in uint layout); +void [[min_sm=6.10]] __builtin_LinAlg_MatrixOuterProduct(out LinAlgMatrix ret, in LinAlg vecA, in LinAlg vecB); +void [[min_sm=6.10]] __builtin_LinAlg_Convert(out LinAlg ret, in LinAlg vec, in uint input_interp, in uint output_interp); +void [[min_sm=6.10]] __builtin_LinAlg_VectorAccumulateToDescriptor(in LinAlg<> vec, in RWByteAddressBuffer buf, in uint offset, in uint align); } namespace