From a6ddf4bd3660f517f5100c1fc49bab29bf550f41 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 12:43:46 -0800 Subject: [PATCH 01/15] Chris's second change --- include/dxc/DXIL/DxilFunctionProps.h | 12 ++++-- include/dxc/DXIL/DxilMetadataHelper.h | 1 + lib/DXIL/DxilMetadataHelper.cpp | 39 +++++++++++++++----- lib/DXIL/DxilModule.cpp | 4 +- lib/DxilContainer/DxilContainerAssembler.cpp | 9 ++--- lib/HLSL/DxilValidation.cpp | 6 +-- tools/clang/include/clang/Basic/Attr.td | 2 +- tools/clang/lib/CodeGen/CGHLSLMS.cpp | 7 +++- tools/clang/lib/Sema/SemaHLSL.cpp | 19 +++++++--- 9 files changed, 67 insertions(+), 32 deletions(-) diff --git a/include/dxc/DXIL/DxilFunctionProps.h b/include/dxc/DXIL/DxilFunctionProps.h index 26f70244d0..04b74a4c36 100644 --- a/include/dxc/DXIL/DxilFunctionProps.h +++ b/include/dxc/DXIL/DxilFunctionProps.h @@ -34,7 +34,9 @@ struct DxilFunctionProps { memset(&Node, 0, sizeof(Node)); Node.LaunchType = DXIL::NodeLaunchType::Invalid; Node.LocalRootArgumentsTableIndex = -1; - waveSize = 0; + waveMinSize = 0; + waveMaxSize = 0; + wavePreferredSize = 0; } union { // Geometry shader. @@ -107,9 +109,11 @@ struct DxilFunctionProps { std::vector InputNodes; std::vector OutputNodes; - // WaveSize is currently allowed only on compute shaders, but could be - // supported on other shader types in the future - unsigned waveSize; + // SM 6.6 allows WaveSize specification for only a single required size. SM + // 6.8+ allows specification of WaveSize as a min, max and preferred value. + unsigned waveMinSize; + unsigned waveMaxSize; + unsigned wavePreferredSize; // Save root signature for lib profile entry. std::vector serializedRootSignature; void SetSerializedRootSignature(const uint8_t *pData, unsigned size) { diff --git a/include/dxc/DXIL/DxilMetadataHelper.h b/include/dxc/DXIL/DxilMetadataHelper.h index 06f9919f31..ff761a18e3 100644 --- a/include/dxc/DXIL/DxilMetadataHelper.h +++ b/include/dxc/DXIL/DxilMetadataHelper.h @@ -318,6 +318,7 @@ class DxilMDHelper { static const unsigned kDxilNodeInputsTag = 20; static const unsigned kDxilNodeOutputsTag = 21; static const unsigned kDxilNodeMaxDispatchGridTag = 22; + static const unsigned kDxilRangedWaveSizeTag = 23; // Node Input/Output State. static const unsigned kDxilNodeOutputIDTag = 0; diff --git a/lib/DXIL/DxilMetadataHelper.cpp b/lib/DXIL/DxilMetadataHelper.cpp index a970e7a62b..05d0201bf5 100644 --- a/lib/DXIL/DxilMetadataHelper.cpp +++ b/lib/DXIL/DxilMetadataHelper.cpp @@ -1596,10 +1596,17 @@ MDTuple *DxilMDHelper::EmitDxilEntryProperties(uint64_t rawShaderFlag, NumThreadVals.emplace_back(Uint32ToConstMD(props.numThreads[2])); MDVals.emplace_back(MDNode::get(m_Ctx, NumThreadVals)); - if (props.waveSize != 0) { - MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilWaveSizeTag)); - vector WaveSizeVal; - WaveSizeVal.emplace_back(Uint32ToConstMD(props.waveSize)); + if (props.waveMinSize != 0) { + bool UseRange = props.waveMaxSize != 0; + MDVals.emplace_back( + Uint32ToConstMD(UseRange ? DxilMDHelper::kDxilRangedWaveSizeTag + : DxilMDHelper::kDxilWaveSizeTag)); + SmallVector WaveSizeVal; + WaveSizeVal.emplace_back(Uint32ToConstMD(props.waveMinSize)); + if (UseRange) { + WaveSizeVal.emplace_back(Uint32ToConstMD(props.waveMaxSize)); + WaveSizeVal.emplace_back(Uint32ToConstMD(props.wavePreferredSize)); + } MDVals.emplace_back(MDNode::get(m_Ctx, WaveSizeVal)); } } break; @@ -1823,7 +1830,14 @@ void DxilMDHelper::LoadDxilEntryProperties(const MDOperand &MDO, case DxilMDHelper::kDxilWaveSizeTag: { DXASSERT(props.IsCS() || props.IsNode(), "else invalid shader kind"); MDNode *pNode = cast(MDO.get()); - props.waveSize = ConstMDToUint32(pNode->getOperand(0)); + props.waveMinSize = ConstMDToUint32(pNode->getOperand(0)); + } break; + case DxilMDHelper::kDxilRangedWaveSizeTag: { + DXASSERT(props.IsCS() || props.IsNode(), "else invalid shader kind"); + MDNode *pNode = cast(MDO.get()); + props.waveMinSize = ConstMDToUint32(pNode->getOperand(0)); + props.waveMaxSize = ConstMDToUint32(pNode->getOperand(1)); + props.wavePreferredSize = ConstMDToUint32(pNode->getOperand(2)); } break; case DxilMDHelper::kDxilEntryRootSigTag: { MDNode *pNode = cast(MDO.get()); @@ -2644,10 +2658,17 @@ void DxilMDHelper::EmitDxilNodeState(std::vector &MDVals, // Optional Fields - if (props.waveSize != 0) { - MDVals.emplace_back(Uint32ToConstMD(DxilMDHelper::kDxilWaveSizeTag)); - vector WaveSizeVal; - WaveSizeVal.emplace_back(Uint32ToConstMD(props.waveSize)); + if (props.waveMinSize != 0) { + bool UseRange = props.waveMaxSize != 0; + MDVals.emplace_back( + Uint32ToConstMD(UseRange ? DxilMDHelper::kDxilRangedWaveSizeTag + : DxilMDHelper::kDxilWaveSizeTag)); + SmallVector WaveSizeVal; + WaveSizeVal.emplace_back(Uint32ToConstMD(props.waveMinSize)); + if (UseRange) { + WaveSizeVal.emplace_back(Uint32ToConstMD(props.waveMaxSize)); + WaveSizeVal.emplace_back(Uint32ToConstMD(props.wavePreferredSize)); + } MDVals.emplace_back(MDNode::get(m_Ctx, WaveSizeVal)); } diff --git a/lib/DXIL/DxilModule.cpp b/lib/DXIL/DxilModule.cpp index 7098e9db01..fca7de3c84 100644 --- a/lib/DXIL/DxilModule.cpp +++ b/lib/DXIL/DxilModule.cpp @@ -400,7 +400,7 @@ void DxilModule::SetWaveSize(unsigned size) { "only works for CS profile"); DxilFunctionProps &props = m_DxilEntryPropsMap.begin()->second->props; DXASSERT_NOMSG(m_pSM->GetKind() == props.shaderKind); - props.waveSize = size; + props.waveMinSize = size; } unsigned DxilModule::GetWaveSize() const { @@ -410,7 +410,7 @@ unsigned DxilModule::GetWaveSize() const { return 0; const DxilFunctionProps &props = m_DxilEntryPropsMap.begin()->second->props; DXASSERT_NOMSG(m_pSM->GetKind() == props.shaderKind); - return props.waveSize; + return props.waveMinSize; } DXIL::InputPrimitive DxilModule::GetInputPrimitive() const { diff --git a/lib/DxilContainer/DxilContainerAssembler.cpp b/lib/DxilContainer/DxilContainerAssembler.cpp index 30d81f821c..f78b296203 100644 --- a/lib/DxilContainer/DxilContainerAssembler.cpp +++ b/lib/DxilContainer/DxilContainerAssembler.cpp @@ -1812,11 +1812,10 @@ class DxilRDATWriter : public DxilPartWriter { shaderKind = (uint32_t)props.shaderKind; if (pInfo2 && DM.HasDxilEntryProps(&function)) { const auto &entryProps = DM.GetDxilEntryProps(&function); - unsigned waveSize = entryProps.props.waveSize; - if (waveSize) { - pInfo2->MinimumExpectedWaveLaneCount = waveSize; - pInfo2->MaximumExpectedWaveLaneCount = waveSize; - } + pInfo2->MinimumExpectedWaveLaneCount = entryProps.props.waveMinSize; + pInfo2->MaximumExpectedWaveLaneCount = + entryProps.props.waveMaxSize > 0 ? entryProps.props.waveMaxSize + : entryProps.props.waveMinSize; pInfo2->ShaderFlags = 0; if (entryProps.props.IsNode()) { shaderInfo = AddShaderNodeInfo(DM, function, entryProps, *pInfo2, diff --git a/lib/HLSL/DxilValidation.cpp b/lib/HLSL/DxilValidation.cpp index 982d4ce0da..ae11a2caf8 100644 --- a/lib/HLSL/DxilValidation.cpp +++ b/lib/HLSL/DxilValidation.cpp @@ -5251,15 +5251,15 @@ static void ValidateEntryProps(ValidationContext &ValCtx, // validate wave size (currently allowed only on CS but might be supported on // other shader types in the future) - if (props.waveSize != 0) { + if (props.waveMinSize != 0) { if (DXIL::CompareVersions(ValCtx.m_DxilMajor, ValCtx.m_DxilMinor, 1, 6) < 0) { ValCtx.EmitFnFormatError(F, ValidationRule::SmWaveSizeNeedsDxil16Plus, {}); } - if (!DXIL::IsValidWaveSizeValue(props.waveSize)) { + if (!DXIL::IsValidWaveSizeValue(props.waveMinSize)) { ValCtx.EmitFnFormatError(F, ValidationRule::SmWaveSizeValue, - {std::to_string(props.waveSize), + {std::to_string(props.waveMinSize), std::to_string(DXIL::kMinWaveSize), std::to_string(DXIL::kMaxWaveSize)}); } diff --git a/tools/clang/include/clang/Basic/Attr.td b/tools/clang/include/clang/Basic/Attr.td index 19d1e6b9eb..c6480c8c8a 100644 --- a/tools/clang/include/clang/Basic/Attr.td +++ b/tools/clang/include/clang/Basic/Attr.td @@ -908,7 +908,7 @@ def HLSLWaveSensitive : InheritableAttr { def HLSLWaveSize : InheritableAttr { let Spellings = [CXX11<"", "wavesize", 2017>]; - let Args = [IntArgument<"Size">]; + let Args = [IntArgument<"Min">, DefaultIntArgument<"Max", 0>, DefaultIntArgument<"Preferred", 0>]; let Documentation = [Undocumented]; } diff --git a/tools/clang/lib/CodeGen/CGHLSLMS.cpp b/tools/clang/lib/CodeGen/CGHLSLMS.cpp index 1c5bebfcee..e0c793c592 100644 --- a/tools/clang/lib/CodeGen/CGHLSLMS.cpp +++ b/tools/clang/lib/CodeGen/CGHLSLMS.cpp @@ -1809,8 +1809,11 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) { funcProps->ShaderProps.PS.EarlyDepthStencil = true; } - if (const HLSLWaveSizeAttr *Attr = FD->getAttr()) - funcProps->waveSize = Attr->getSize(); + if (const HLSLWaveSizeAttr *Attr = FD->getAttr()) { + funcProps->waveMinSize = Attr->getMin(); + funcProps->waveMaxSize = Attr->getMax(); + funcProps->wavePreferredSize = Attr->getPreferred(); + } // Node shader if (isNode) { diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 05a278f369..05674dd485 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -12620,11 +12620,12 @@ HLSLWaveSizeAttr *ValidateWaveSizeAttributes(Sema &S, Decl *D, const AttributeList &A) { // validate that the wavesize argument is a power of 2 between 4 and 128 // inclusive - HLSLWaveSizeAttr *pAttr = ::new (S.Context) - HLSLWaveSizeAttr(A.getRange(), S.Context, ValidateAttributeIntArg(S, A), - A.getAttributeSpellingListIndex()); + HLSLWaveSizeAttr *pAttr = ::new (S.Context) HLSLWaveSizeAttr( + A.getRange(), S.Context, ValidateAttributeIntArg(S, A, 0), + ValidateAttributeIntArg(S, A, 1), ValidateAttributeIntArg(S, A, 2), + A.getAttributeSpellingListIndex()); - unsigned waveSize = pAttr->getSize(); + unsigned waveSize = pAttr->getMin(); if (!DXIL::IsValidWaveSizeValue(waveSize)) { S.Diag(A.getLoc(), diag::err_hlsl_wavesize_size) << DXIL::kMinWaveSize << DXIL::kMaxWaveSize; @@ -12634,7 +12635,7 @@ HLSLWaveSizeAttr *ValidateWaveSizeAttributes(Sema &S, Decl *D, // wavesize attribute on the decl HLSLWaveSizeAttr *waveSizeAttr = D->getAttr(); if (waveSizeAttr) { - if (waveSizeAttr->getSize() != pAttr->getSize()) { + if (waveSizeAttr->getMin() != pAttr->getMin()) { S.Diag(A.getLoc(), diag::err_hlsl_conflicting_shader_attribute) << pAttr->getSpelling() << waveSizeAttr->getSpelling(); S.Diag(waveSizeAttr->getLocation(), diag::note_conflicting_attribute); @@ -14609,7 +14610,13 @@ void hlsl::CustomPrintHLSLAttr(const clang::Attr *A, llvm::raw_ostream &Out, Attr *noconst = const_cast(A); HLSLWaveSizeAttr *ACast = static_cast(noconst); Indent(Indentation, Out); - Out << "[wavesize(" << ACast->getSize() << ")]\n"; + Out << "[wavesize(" << ACast->getMin(); + if (ACast->getMax() > 0) { + Out << ", " << ACast->getMax(); + if (ACast->getPreferred() > 0) + Out << ", " << ACast->getPreferred(); + } + Out << ")]\n"; break; } From 2970e920a00722df381e77b8557c771df5556cbb Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 15:31:49 -0800 Subject: [PATCH 02/15] add testing and validation! --- docs/DXIL.rst | 2 + include/dxc/DXIL/DxilConstants.h | 19 ++- lib/HLSL/DxilValidation.cpp | 20 ++- tools/clang/lib/Sema/SemaHLSL.cpp | 23 +++- .../hlsl/workgraph/wavesize_range.hlsl | 120 ++++++++++++++++++ .../hlsl/workgraph/wavesize_range.ll | 51 ++++++++ .../hlsl/workgraph/wavesize_range2.ll | 51 ++++++++ .../hlsl/workgraph/wavesize_range3.ll | 51 ++++++++ utils/hct/hctdb.py | 8 ++ 9 files changed, 338 insertions(+), 7 deletions(-) create mode 100644 tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.hlsl create mode 100644 tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.ll create mode 100644 tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range2.ll create mode 100644 tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range3.ll diff --git a/docs/DXIL.rst b/docs/DXIL.rst index 9d050ed3a5..cfcc87dfec 100644 --- a/docs/DXIL.rst +++ b/docs/DXIL.rst @@ -3261,7 +3261,9 @@ SM.TRIOUTPUTPRIMITIVEMISMATCH Hull Shader declared with Tri Domain m SM.UNDEFINEDOUTPUT Not all elements of output %0 were written. SM.VALIDDOMAIN Invalid Tessellator Domain specified. Must be isoline, tri or quad. SM.VIEWIDNEEDSSLOT ViewID requires compatible space in pixel shader input signature +SM.WAVESIZEMINGEQMAX Declared Minimum WaveSize %0 greater or equal to declared Maximum Wavesize %1 SM.WAVESIZENEEDSDXIL16PLUS WaveSize is valid only for DXIL version 1.6 and higher. +SM.WAVESIZEPREFERREDOUTOFRANGE Preferred WaveSize %0 outside valid range [%1..%2] SM.WAVESIZEVALUE Declared WaveSize %0 outside valid range [%1..%2], or not a power of 2. SM.ZEROHSINPUTCONTROLPOINTWITHINPUT When HS input control point count is 0, no input signature should exist. TYPES.DEFINED Type must be defined based on DXIL primitives diff --git a/include/dxc/DXIL/DxilConstants.h b/include/dxc/DXIL/DxilConstants.h index 8712b0fd9c..afaefc5252 100644 --- a/include/dxc/DXIL/DxilConstants.h +++ b/include/dxc/DXIL/DxilConstants.h @@ -448,10 +448,23 @@ inline bool IsFeedbackTexture(DXIL::ResourceKind ResourceKind) { ResourceKind == DXIL::ResourceKind::FeedbackTexture2DArray; } -inline bool IsValidWaveSizeValue(unsigned size) { +inline bool isPowerOf2(unsigned x) { return (x & (x - 1)) == 0; } + +inline bool IsValidWaveSizeValue(unsigned min_wave, unsigned max_wave, + unsigned pref_wave) { // must be power of 2 between 4 and 128 - return size >= kMinWaveSize && size <= kMaxWaveSize && - (size & (size - 1)) == 0; + bool minIsValid = min_wave >= kMinWaveSize && min_wave <= kMaxWaveSize && + isPowerOf2(min_wave); + if (max_wave == 0) + return true; + bool maxIsValid = max_wave >= kMinWaveSize && max_wave <= kMaxWaveSize && + isPowerOf2(max_wave); + // 0 is a valid value for the preferred wave size + bool prefIsValid = + pref_wave == 0 || (pref_wave >= kMinWaveSize && + pref_wave <= kMaxWaveSize && isPowerOf2(pref_wave)); + + return minIsValid && maxIsValid && prefIsValid; } // TODO: change opcodes. diff --git a/lib/HLSL/DxilValidation.cpp b/lib/HLSL/DxilValidation.cpp index ae11a2caf8..9aeea0816b 100644 --- a/lib/HLSL/DxilValidation.cpp +++ b/lib/HLSL/DxilValidation.cpp @@ -5257,12 +5257,30 @@ static void ValidateEntryProps(ValidationContext &ValCtx, ValCtx.EmitFnFormatError(F, ValidationRule::SmWaveSizeNeedsDxil16Plus, {}); } - if (!DXIL::IsValidWaveSizeValue(props.waveMinSize)) { + if (!DXIL::IsValidWaveSizeValue(props.waveMinSize, props.waveMaxSize, + props.wavePreferredSize)) { ValCtx.EmitFnFormatError(F, ValidationRule::SmWaveSizeValue, {std::to_string(props.waveMinSize), std::to_string(DXIL::kMinWaveSize), std::to_string(DXIL::kMaxWaveSize)}); } + + bool prefInRange = props.wavePreferredSize == 0 + ? true + : props.wavePreferredSize >= props.waveMinSize && + props.wavePreferredSize <= props.waveMaxSize; + if (!prefInRange) { + ValCtx.EmitFnFormatError(F, ValidationRule::SmWaveSizePreferredOutOfRange, + {std::to_string(props.wavePreferredSize), + std::to_string(props.waveMinSize), + std::to_string(props.waveMaxSize)}); + } + + if (props.waveMaxSize != 0 && props.waveMinSize >= props.waveMaxSize) { + ValCtx.EmitFnFormatError(F, ValidationRule::SmWaveSizeMinGEQMax, + {std::to_string(props.waveMinSize), + std::to_string(props.waveMaxSize)}); + } } if (ShaderType == DXIL::ShaderKind::Compute || props.IsNode()) { diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 05674dd485..3f9e5fbc59 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -12625,17 +12625,34 @@ HLSLWaveSizeAttr *ValidateWaveSizeAttributes(Sema &S, Decl *D, ValidateAttributeIntArg(S, A, 1), ValidateAttributeIntArg(S, A, 2), A.getAttributeSpellingListIndex()); - unsigned waveSize = pAttr->getMin(); - if (!DXIL::IsValidWaveSizeValue(waveSize)) { + unsigned minWave = pAttr->getMin(); + unsigned maxWave = pAttr->getMax(); + unsigned prefWave = pAttr->getPreferred(); + + if (!DXIL::IsValidWaveSizeValue(minWave, maxWave, prefWave)) { S.Diag(A.getLoc(), diag::err_hlsl_wavesize_size) << DXIL::kMinWaveSize << DXIL::kMaxWaveSize; } + bool prefInRange = + prefWave == 0 ? true : prefWave >= minWave && prefWave <= maxWave; + if (!prefInRange) { + S.Diag(A.getLoc(), diag::err_hlsl_wavesize_pref_size_out_of_range) + << prefWave << minWave << maxWave; + } + + if (maxWave != 0 && minWave >= maxWave) { + S.Diag(A.getLoc(), diag::err_hlsl_wavesize_min_geq_max) + << minWave << maxWave; + } + // make sure there is not already an existing conflicting // wavesize attribute on the decl HLSLWaveSizeAttr *waveSizeAttr = D->getAttr(); if (waveSizeAttr) { - if (waveSizeAttr->getMin() != pAttr->getMin()) { + if (waveSizeAttr->getMin() != pAttr->getMin() || + waveSizeAttr->getMax() != pAttr->getMax() || + waveSizeAttr->getPreferred() != pAttr->getPreferred()) { S.Diag(A.getLoc(), diag::err_hlsl_conflicting_shader_attribute) << pAttr->getSpelling() << waveSizeAttr->getSpelling(); S.Diag(waveSizeAttr->getLocation(), diag::note_conflicting_attribute); diff --git a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.hlsl b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.hlsl new file mode 100644 index 0000000000..ce391999fa --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.hlsl @@ -0,0 +1,120 @@ +// RUN: %dxc -T lib_6_8 %s | FileCheck %s + +// Check the WaveSize attribute is accepted by work graph nodes +// and appears in the metadata + +struct INPUT_RECORD +{ + uint DispatchGrid1 : SV_DispatchGrid; + uint2 a; +}; + + + +// CHECK: error: Preferred WaveSize value 32 must be between 4 and 16 +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(4, 16, 32)] +void node01(DispatchNodeInputRecord input) { } + +// CHECK: error: Preferred WaveSize value 32 must be between 16 and 16 +// CHECK: error: Minimum WaveSize value 16 must be less than Maximum WaveSize value 16 +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(16, 16, 32)] +void node02(DispatchNodeInputRecord input) { } + +// CHECK: error: Minimum WaveSize value 16 must be less than Maximum WaveSize value 16 +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(16, 16, 16)] +void node03(DispatchNodeInputRecord input) { } + +// the non-power of 2 diagnostic gets emitted once, regardless of how many arguments aren't powers of 2. +// CHECK: WaveSize arguments must be between 4 and 128 and a power of 2 +// CHECK: Preferred WaveSize value 32 must be between 15 and 17 +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(15, 17, 32)] +void node04(DispatchNodeInputRecord input) { } + +// CHECK: WaveSize arguments must be between 4 and 128 and a power of 2 +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(-15, 16, 8)] +void node05(DispatchNodeInputRecord input) { } + +// CHECK: error: 'WaveSize' attribute takes no more than 3 arguments +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(4, 16, 8, 8)] +void node06(DispatchNodeInputRecord input) { } + +// CHECK: error: 'WaveSize' attribute takes at least 1 argument +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize()] +void node07(DispatchNodeInputRecord input) { } + +// CHECK: error: 'WaveSize' attribute requires an integer constant +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(4, 8, node07)] +void node08(DispatchNodeInputRecord input) { } + +// CHECK: error: shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize' +// CHECK: note: conflicting attribute is here +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(8, 32, 8)] +[WaveSize(4, 32, 8)] +void node09(DispatchNodeInputRecord input) { } + +// CHECK: error: shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize' +// CHECK: note: conflicting attribute is here +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(8, 32, 8)] +[WaveSize(8, 16, 8)] +void node10(DispatchNodeInputRecord input) { } + +// CHECK: error: shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize' +// CHECK: note: conflicting attribute is here +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(4, 8, 8)] +[WaveSize(4, 8, 4)] +void node11(DispatchNodeInputRecord input) { } + + +// CHECK: error: shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize' +// CHECK: note: conflicting attribute is here +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(4, 8, 4)] +[WaveSize(4)] +void node12(DispatchNodeInputRecord input) { } diff --git a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.ll b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.ll new file mode 100644 index 0000000000..518d3aff48 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.ll @@ -0,0 +1,51 @@ +; RUN: %dxv %s | FileCheck %s + +; This tests the validator on emitting errors for invalid +; arguments in the wavesize range attribute for entry point functions. +; This test tests that when the preferred value lies outside of the given +; minimum and maximum value range, an error is emitted. + +; shader hash: e935848c1a904483af91f615705c305c +; +; Buffer Definitions: +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +define void @node01() { + ret void +} + +!llvm.ident = !{!0} +!dx.version = !{!1} +!dx.valver = !{!1} +!dx.shaderModel = !{!2} +!dx.typeAnnotations = !{!3} +!dx.entryPoints = !{!7, !8} + +!0 = !{!"dxc(private) 1.7.0.4390 (dxil_validation_on_sv_value_node_launch, 6a52940e2258)"} +!1 = !{i32 1, i32 8} +!2 = !{!"lib", i32 6, i32 8} +!3 = !{i32 1, void ()* @node01, !4} +!4 = !{!5} +!5 = !{i32 0, !6, !6} +!6 = !{} +!7 = !{null, !"", null, null, null} +!8 = !{void ()* @node01, !"node01", null, null, !9} +!9 = !{i32 8, i32 15, i32 13, i32 1, i32 23, !10, i32 15, !11, i32 16, i32 -1, i32 22, !12, i32 20, !13, i32 4, !17, i32 5, !18} +; CHECK: error: Preferred WaveSize 32 outside valid range [4..16] +!10 = !{i32 4, i32 16, i32 32} +!11 = !{!"node01", i32 0} +!12 = !{i32 32, i32 1, i32 1} +!13 = !{!14} +!14 = !{i32 1, i32 97, i32 2, !15} +!15 = !{i32 0, i32 12, i32 1, !16} +!16 = !{i32 0, i32 5, i32 1} +!17 = !{i32 1, i32 1, i32 1} +!18 = !{i32 0} \ No newline at end of file diff --git a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range2.ll b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range2.ll new file mode 100644 index 0000000000..e28130295b --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range2.ll @@ -0,0 +1,51 @@ +; RUN: %dxv %s | FileCheck %s + +; This tests the validator on emitting errors for invalid +; arguments in the wavesize range attribute for entry point functions. +; This test tests that when the preferred value lies outside of the given +; minimum and maximum value range, an error is emitted. + +; shader hash: e935848c1a904483af91f615705c305c +; +; Buffer Definitions: +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +define void @node01() { + ret void +} + +!llvm.ident = !{!0} +!dx.version = !{!1} +!dx.valver = !{!1} +!dx.shaderModel = !{!2} +!dx.typeAnnotations = !{!3} +!dx.entryPoints = !{!7, !8} + +!0 = !{!"dxc(private) 1.7.0.4390 (dxil_validation_on_sv_value_node_launch, 6a52940e2258)"} +!1 = !{i32 1, i32 8} +!2 = !{!"lib", i32 6, i32 8} +!3 = !{i32 1, void ()* @node01, !4} +!4 = !{!5} +!5 = !{i32 0, !6, !6} +!6 = !{} +!7 = !{null, !"", null, null, null} +!8 = !{void ()* @node01, !"node01", null, null, !9} +!9 = !{i32 8, i32 15, i32 13, i32 1, i32 23, !10, i32 15, !11, i32 16, i32 -1, i32 22, !12, i32 20, !13, i32 4, !17, i32 5, !18} +; CHECK: error: Declared Minimum WaveSize 16 greater or equal to declared Maximum Wavesize 16 +!10 = !{i32 16, i32 16, i32 16} +!11 = !{!"node01", i32 0} +!12 = !{i32 32, i32 1, i32 1} +!13 = !{!14} +!14 = !{i32 1, i32 97, i32 2, !15} +!15 = !{i32 0, i32 12, i32 1, !16} +!16 = !{i32 0, i32 5, i32 1} +!17 = !{i32 1, i32 1, i32 1} +!18 = !{i32 0} \ No newline at end of file diff --git a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range3.ll b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range3.ll new file mode 100644 index 0000000000..97f81979d5 --- /dev/null +++ b/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range3.ll @@ -0,0 +1,51 @@ +; RUN: %dxv %s | FileCheck %s + +; This tests the validator on emitting errors for invalid +; arguments in the wavesize range attribute for entry point functions. +; This test tests that when the preferred value lies outside of the given +; minimum and maximum value range, an error is emitted. + +; shader hash: e935848c1a904483af91f615705c305c +; +; Buffer Definitions: +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +define void @node01() { + ret void +} + +!llvm.ident = !{!0} +!dx.version = !{!1} +!dx.valver = !{!1} +!dx.shaderModel = !{!2} +!dx.typeAnnotations = !{!3} +!dx.entryPoints = !{!7, !8} + +!0 = !{!"dxc(private) 1.7.0.4390 (dxil_validation_on_sv_value_node_launch, 6a52940e2258)"} +!1 = !{i32 1, i32 8} +!2 = !{!"lib", i32 6, i32 8} +!3 = !{i32 1, void ()* @node01, !4} +!4 = !{!5} +!5 = !{i32 0, !6, !6} +!6 = !{} +!7 = !{null, !"", null, null, null} +!8 = !{void ()* @node01, !"node01", null, null, !9} +!9 = !{i32 8, i32 15, i32 13, i32 1, i32 23, !10, i32 15, !11, i32 16, i32 -1, i32 22, !12, i32 20, !13, i32 4, !17, i32 5, !18} +; CHECK: error: Declared WaveSize 15 outside valid range [4..128], or not a power of 2. +!10 = !{i32 15, i32 16, i32 16} +!11 = !{!"node01", i32 0} +!12 = !{i32 32, i32 1, i32 1} +!13 = !{!14} +!14 = !{i32 1, i32 97, i32 2, !15} +!15 = !{i32 0, i32 12, i32 1, !16} +!16 = !{i32 0, i32 5, i32 1} +!17 = !{i32 1, i32 1, i32 1} +!18 = !{i32 0} \ No newline at end of file diff --git a/utils/hct/hctdb.py b/utils/hct/hctdb.py index 35b0201438..56788599e2 100644 --- a/utils/hct/hctdb.py +++ b/utils/hct/hctdb.py @@ -7652,6 +7652,14 @@ def build_valrules(self): self.add_valrule( "Sm.WaveSizeValue", "Declared WaveSize %0 outside valid range [%1..%2], or not a power of 2.", + ) + self.add_valrule( + "Sm.WaveSizePreferredOutOfRange", + "Preferred WaveSize %0 outside valid range [%1..%2]", + ) + self.add_valrule( + "Sm.WaveSizeMinGEQMax", + "Declared Minimum WaveSize %0 greater or equal to declared Maximum Wavesize %1", ) self.add_valrule( "Sm.WaveSizeNeedsDxil16Plus", From 68d0f8bdac69c4f57010b2ecf4b5f388c3825c24 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 16:17:57 -0800 Subject: [PATCH 03/15] move over to verify tests --- .../attributes}/wavesize_range.hlsl | 56 ++++++++++--------- .../attributes}/wavesize_range.ll | 0 .../attributes}/wavesize_range2.ll | 0 .../attributes}/wavesize_range3.ll | 0 4 files changed, 31 insertions(+), 25 deletions(-) rename tools/clang/test/{HLSLFileCheck/hlsl/workgraph => SemaHLSL/attributes}/wavesize_range.hlsl (57%) rename tools/clang/test/{HLSLFileCheck/hlsl/workgraph => SemaHLSL/attributes}/wavesize_range.ll (100%) rename tools/clang/test/{HLSLFileCheck/hlsl/workgraph => SemaHLSL/attributes}/wavesize_range2.ll (100%) rename tools/clang/test/{HLSLFileCheck/hlsl/workgraph => SemaHLSL/attributes}/wavesize_range3.ll (100%) diff --git a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.hlsl b/tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl similarity index 57% rename from tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.hlsl rename to tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl index ce391999fa..b7115d1e1c 100644 --- a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.hlsl +++ b/tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl @@ -1,4 +1,4 @@ -// RUN: %dxc -T lib_6_8 %s | FileCheck %s +// RUN: %dxc -T lib_6_8 -verify %s // Check the WaveSize attribute is accepted by work graph nodes // and appears in the metadata @@ -11,110 +11,116 @@ struct INPUT_RECORD -// CHECK: error: Preferred WaveSize value 32 must be between 4 and 16 [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] -[WaveSize(4, 16, 32)] +[WaveSize(4, 16, 32)] /* expected-error{{Preferred WaveSize value 32 must be between 4 and 16}} */ void node01(DispatchNodeInputRecord input) { } -// CHECK: error: Preferred WaveSize value 32 must be between 16 and 16 -// CHECK: error: Minimum WaveSize value 16 must be less than Maximum WaveSize value 16 + [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] +/* expected-error@+2{{Preferred WaveSize value 32 must be between 16 and 16}} */ +/* expected-error@+1{{Minimum WaveSize value 16 must be less than Maximum WaveSize value 16}} */ [WaveSize(16, 16, 32)] void node02(DispatchNodeInputRecord input) { } -// CHECK: error: Minimum WaveSize value 16 must be less than Maximum WaveSize value 16 [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] -[WaveSize(16, 16, 16)] +[WaveSize(16, 16, 16)] /* expected-error{{Minimum WaveSize value 16 must be less than Maximum WaveSize value 16}} */ void node03(DispatchNodeInputRecord input) { } // the non-power of 2 diagnostic gets emitted once, regardless of how many arguments aren't powers of 2. -// CHECK: WaveSize arguments must be between 4 and 128 and a power of 2 -// CHECK: Preferred WaveSize value 32 must be between 15 and 17 + [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] +/* expected-error@+2{{WaveSize arguments must be between 4 and 128 and a power of 2}} */ +/* expected-error@+1{{Preferred WaveSize value 32 must be between 15 and 17}} */ [WaveSize(15, 17, 32)] void node04(DispatchNodeInputRecord input) { } -// CHECK: WaveSize arguments must be between 4 and 128 and a power of 2 + [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] -[WaveSize(-15, 16, 8)] +/* expected-error@+2{{WaveSize arguments must be between 4 and 128 and a power of 2}} */ +/* expected-warning@+1{{attribute 'WaveSize' must have a uint literal argument}} */ +[WaveSize(-15, 16, 8)] void node05(DispatchNodeInputRecord input) { } -// CHECK: error: 'WaveSize' attribute takes no more than 3 arguments + [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] -[WaveSize(4, 16, 8, 8)] +[WaveSize(4, 16, 8, 8)] /* expected-error{{'WaveSize' attribute takes no more than 3 arguments}} */ void node06(DispatchNodeInputRecord input) { } -// CHECK: error: 'WaveSize' attribute takes at least 1 argument + [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] -[WaveSize()] +[WaveSize()] /* expected-error{{'WaveSize' attribute takes at least 1 argument}} */ void node07(DispatchNodeInputRecord input) { } -// CHECK: error: 'WaveSize' attribute requires an integer constant + [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] -[WaveSize(4, 8, node07)] +[WaveSize(4, 8, node07)] /* expected-error{{'WaveSize' attribute requires an integer constant}} */ void node08(DispatchNodeInputRecord input) { } -// CHECK: error: shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize' -// CHECK: note: conflicting attribute is here + [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] +/* expected-error@+2{{shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize'}} */ +/* expected-note@+2{{conflicting attribute is here}} */ [WaveSize(8, 32, 8)] [WaveSize(4, 32, 8)] void node09(DispatchNodeInputRecord input) { } -// CHECK: error: shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize' -// CHECK: note: conflicting attribute is here + [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] +/* expected-error@+2{{shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize'}} */ +/* expected-note@+2{{conflicting attribute is here}} */ [WaveSize(8, 32, 8)] [WaveSize(8, 16, 8)] void node10(DispatchNodeInputRecord input) { } -// CHECK: error: shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize' -// CHECK: note: conflicting attribute is here + [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] +/* expected-error@+2{{shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize'}} */ +/* expected-note@+2{{conflicting attribute is here}} */ [WaveSize(4, 8, 8)] [WaveSize(4, 8, 4)] void node11(DispatchNodeInputRecord input) { } -// CHECK: error: shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize' -// CHECK: note: conflicting attribute is here + [Shader("node")] [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] +/* expected-error@+2{{shader attribute type 'wavesize' conflicts with shader attribute type 'wavesize'}} */ +/* expected-note@+2{{conflicting attribute is here}} */ [WaveSize(4, 8, 4)] [WaveSize(4)] void node12(DispatchNodeInputRecord input) { } diff --git a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.ll b/tools/clang/test/SemaHLSL/attributes/wavesize_range.ll similarity index 100% rename from tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range.ll rename to tools/clang/test/SemaHLSL/attributes/wavesize_range.ll diff --git a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range2.ll b/tools/clang/test/SemaHLSL/attributes/wavesize_range2.ll similarity index 100% rename from tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range2.ll rename to tools/clang/test/SemaHLSL/attributes/wavesize_range2.ll diff --git a/tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range3.ll b/tools/clang/test/SemaHLSL/attributes/wavesize_range3.ll similarity index 100% rename from tools/clang/test/HLSLFileCheck/hlsl/workgraph/wavesize_range3.ll rename to tools/clang/test/SemaHLSL/attributes/wavesize_range3.ll From 4ff306c8ab523ea1680b95259f7a19f23360f004 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 16:35:34 -0800 Subject: [PATCH 04/15] don't output underflowed numbers in diags --- tools/clang/lib/Sema/SemaHLSL.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 3f9e5fbc59..1f3815acb7 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -12625,9 +12625,9 @@ HLSLWaveSizeAttr *ValidateWaveSizeAttributes(Sema &S, Decl *D, ValidateAttributeIntArg(S, A, 1), ValidateAttributeIntArg(S, A, 2), A.getAttributeSpellingListIndex()); - unsigned minWave = pAttr->getMin(); - unsigned maxWave = pAttr->getMax(); - unsigned prefWave = pAttr->getPreferred(); + int minWave = pAttr->getMin(); + int maxWave = pAttr->getMax(); + int prefWave = pAttr->getPreferred(); if (!DXIL::IsValidWaveSizeValue(minWave, maxWave, prefWave)) { S.Diag(A.getLoc(), diag::err_hlsl_wavesize_size) @@ -12638,12 +12638,12 @@ HLSLWaveSizeAttr *ValidateWaveSizeAttributes(Sema &S, Decl *D, prefWave == 0 ? true : prefWave >= minWave && prefWave <= maxWave; if (!prefInRange) { S.Diag(A.getLoc(), diag::err_hlsl_wavesize_pref_size_out_of_range) - << prefWave << minWave << maxWave; + << (unsigned)prefWave << (unsigned)minWave << (unsigned)maxWave; } if (maxWave != 0 && minWave >= maxWave) { S.Diag(A.getLoc(), diag::err_hlsl_wavesize_min_geq_max) - << minWave << maxWave; + << (unsigned)minWave << (unsigned)maxWave; } // make sure there is not already an existing conflicting From 843335b392b31b08296017ae915ff767bd64a4cb Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 17:31:28 -0800 Subject: [PATCH 05/15] address tex's feedback to the patch --- docs/DXIL.rst | 1 + include/dxc/DXIL/DxilConstants.h | 3 ++- include/dxc/DXIL/DxilModule.h | 3 ++- lib/DXIL/DxilMetadataHelper.cpp | 9 +++++++-- lib/DXIL/DxilModule.cpp | 12 +++++++++++- lib/DxilContainer/DxilContainerAssembler.cpp | 9 +++++---- lib/HLSL/DxilValidation.cpp | 8 ++++++++ tools/clang/lib/Sema/SemaHLSL.cpp | 18 ++++++++++++++++++ .../SemaHLSL/attributes/wavesize_range.hlsl | 3 +-- utils/hct/hctdb.py | 4 ++++ 10 files changed, 59 insertions(+), 11 deletions(-) diff --git a/docs/DXIL.rst b/docs/DXIL.rst index cfcc87dfec..f0d00bb9ba 100644 --- a/docs/DXIL.rst +++ b/docs/DXIL.rst @@ -3264,6 +3264,7 @@ SM.VIEWIDNEEDSSLOT ViewID requires compatible space in pi SM.WAVESIZEMINGEQMAX Declared Minimum WaveSize %0 greater or equal to declared Maximum Wavesize %1 SM.WAVESIZENEEDSDXIL16PLUS WaveSize is valid only for DXIL version 1.6 and higher. SM.WAVESIZEPREFERREDOUTOFRANGE Preferred WaveSize %0 outside valid range [%1..%2] +SM.WAVESIZERANGENEEDSDXIL18PLUS WaveSize Range is valid only for DXIL version 1.8 and higher. SM.WAVESIZEVALUE Declared WaveSize %0 outside valid range [%1..%2], or not a power of 2. SM.ZEROHSINPUTCONTROLPOINTWITHINPUT When HS input control point count is 0, no input signature should exist. TYPES.DEFINED Type must be defined based on DXIL primitives diff --git a/include/dxc/DXIL/DxilConstants.h b/include/dxc/DXIL/DxilConstants.h index afaefc5252..b723cc3991 100644 --- a/include/dxc/DXIL/DxilConstants.h +++ b/include/dxc/DXIL/DxilConstants.h @@ -456,7 +456,8 @@ inline bool IsValidWaveSizeValue(unsigned min_wave, unsigned max_wave, bool minIsValid = min_wave >= kMinWaveSize && min_wave <= kMaxWaveSize && isPowerOf2(min_wave); if (max_wave == 0) - return true; + return minIsValid; + bool maxIsValid = max_wave >= kMinWaveSize && max_wave <= kMaxWaveSize && isPowerOf2(max_wave); // 0 is a valid value for the preferred wave size diff --git a/include/dxc/DXIL/DxilModule.h b/include/dxc/DXIL/DxilModule.h index a5e40b536e..8672cbe186 100644 --- a/include/dxc/DXIL/DxilModule.h +++ b/include/dxc/DXIL/DxilModule.h @@ -256,7 +256,8 @@ class DxilModule { // Compute shader void SetWaveSize(unsigned size); - unsigned GetWaveSize() const; + unsigned GetMinWaveSize() const; + unsigned GetMaxWaveSize() const; // Geometry shader. DXIL::InputPrimitive GetInputPrimitive() const; diff --git a/lib/DXIL/DxilMetadataHelper.cpp b/lib/DXIL/DxilMetadataHelper.cpp index 05d0201bf5..f00e221aea 100644 --- a/lib/DXIL/DxilMetadataHelper.cpp +++ b/lib/DXIL/DxilMetadataHelper.cpp @@ -1598,6 +1598,9 @@ MDTuple *DxilMDHelper::EmitDxilEntryProperties(uint64_t rawShaderFlag, if (props.waveMinSize != 0) { bool UseRange = props.waveMaxSize != 0; + if (UseRange) + DXASSERT(DXIL::CompareVersions(m_MinValMajor, m_MinValMinor, 1, 8) >= 0, + "DXIL version must be > 1.8"); MDVals.emplace_back( Uint32ToConstMD(UseRange ? DxilMDHelper::kDxilRangedWaveSizeTag : DxilMDHelper::kDxilWaveSizeTag)); @@ -1828,12 +1831,14 @@ void DxilMDHelper::LoadDxilEntryProperties(const MDOperand &MDO, LoadDxilASState(MDO, props.numThreads, AS.payloadSizeInBytes); } break; case DxilMDHelper::kDxilWaveSizeTag: { - DXASSERT(props.IsCS() || props.IsNode(), "else invalid shader kind"); MDNode *pNode = cast(MDO.get()); props.waveMinSize = ConstMDToUint32(pNode->getOperand(0)); } break; case DxilMDHelper::kDxilRangedWaveSizeTag: { - DXASSERT(props.IsCS() || props.IsNode(), "else invalid shader kind"); + // if we're here, we're using the range variant. + // Extra metadata is used is SM < 6.8 + if (!m_pSM->IsSMAtLeast(6, 8)) + m_bExtraMetadata = true; MDNode *pNode = cast(MDO.get()); props.waveMinSize = ConstMDToUint32(pNode->getOperand(0)); props.waveMaxSize = ConstMDToUint32(pNode->getOperand(1)); diff --git a/lib/DXIL/DxilModule.cpp b/lib/DXIL/DxilModule.cpp index fca7de3c84..c2de3ae86e 100644 --- a/lib/DXIL/DxilModule.cpp +++ b/lib/DXIL/DxilModule.cpp @@ -403,7 +403,7 @@ void DxilModule::SetWaveSize(unsigned size) { props.waveMinSize = size; } -unsigned DxilModule::GetWaveSize() const { +unsigned DxilModule::GetMinWaveSize() const { DXASSERT(m_DxilEntryPropsMap.size() == 1 && m_pSM->IsCS(), "only works for CS profiles"); if (!m_pSM->IsCS()) @@ -413,6 +413,16 @@ unsigned DxilModule::GetWaveSize() const { return props.waveMinSize; } +unsigned DxilModule::GetMaxWaveSize() const { + DXASSERT(m_DxilEntryPropsMap.size() == 1 && m_pSM->IsCS(), + "only works for CS profiles"); + if (!m_pSM->IsCS()) + return 0; + const DxilFunctionProps &props = m_DxilEntryPropsMap.begin()->second->props; + DXASSERT_NOMSG(m_pSM->GetKind() == props.shaderKind); + return props.waveMaxSize; +} + DXIL::InputPrimitive DxilModule::GetInputPrimitive() const { if (!m_pSM->IsGS()) return DXIL::InputPrimitive::Undefined; diff --git a/lib/DxilContainer/DxilContainerAssembler.cpp b/lib/DxilContainer/DxilContainerAssembler.cpp index f78b296203..ab0e5249bf 100644 --- a/lib/DxilContainer/DxilContainerAssembler.cpp +++ b/lib/DxilContainer/DxilContainerAssembler.cpp @@ -941,10 +941,11 @@ class DxilPSVWriter : public DxilPartWriter { break; } case ShaderModel::Kind::Compute: { - UINT waveSize = (UINT)m_Module.GetWaveSize(); - if (waveSize != 0) { - pInfo->MinimumExpectedWaveLaneCount = waveSize; - pInfo->MaximumExpectedWaveLaneCount = waveSize; + UINT waveMinSize = (UINT)m_Module.GetMinWaveSize(); + UINT waveMaxSize = (UINT)m_Module.GetMaxWaveSize(); + if (waveMinSize != 0) { + pInfo->MinimumExpectedWaveLaneCount = waveMinSize; + pInfo->MaximumExpectedWaveLaneCount = waveMaxSize; } break; } diff --git a/lib/HLSL/DxilValidation.cpp b/lib/HLSL/DxilValidation.cpp index 9aeea0816b..ba365946a8 100644 --- a/lib/HLSL/DxilValidation.cpp +++ b/lib/HLSL/DxilValidation.cpp @@ -5252,6 +5252,14 @@ static void ValidateEntryProps(ValidationContext &ValCtx, // validate wave size (currently allowed only on CS but might be supported on // other shader types in the future) if (props.waveMinSize != 0) { + + if (props.waveMaxSize != 0) { + if (DXIL::CompareVersions(ValCtx.m_DxilMajor, ValCtx.m_DxilMinor, 1, 8) < + 0) { + ValCtx.EmitFnFormatError(F, ValidationRule::SmWaveSizeRangeNeedsDxil18Plus, + {}); + } + } if (DXIL::CompareVersions(ValCtx.m_DxilMajor, ValCtx.m_DxilMinor, 1, 6) < 0) { ValCtx.EmitFnFormatError(F, ValidationRule::SmWaveSizeNeedsDxil16Plus, diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 1f3815acb7..9d262b5f46 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -12629,11 +12629,29 @@ HLSLWaveSizeAttr *ValidateWaveSizeAttributes(Sema &S, Decl *D, int maxWave = pAttr->getMax(); int prefWave = pAttr->getPreferred(); + // canonicalize degenerate cases. + if (maxWave == minWave) { + pAttr->setMax(0); + maxWave = 0; + } + if (maxWave == 0 && prefWave != 0) { + if (prefWave == minWave) { + pAttr->setPreferred(0); + prefWave = 0; + } + else{ + S.Diag(A.getLoc(), diag::err_hlsl_wavesize_pref_size_out_of_range) + << (unsigned)prefWave << (unsigned)minWave << (unsigned)maxWave; + } + } + + // validate attribute arguments. if (!DXIL::IsValidWaveSizeValue(minWave, maxWave, prefWave)) { S.Diag(A.getLoc(), diag::err_hlsl_wavesize_size) << DXIL::kMinWaveSize << DXIL::kMaxWaveSize; } + bool prefInRange = prefWave == 0 ? true : prefWave >= minWave && prefWave <= maxWave; if (!prefInRange) { diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl b/tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl index b7115d1e1c..20b268cc6a 100644 --- a/tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl +++ b/tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl @@ -1,7 +1,6 @@ // RUN: %dxc -T lib_6_8 -verify %s -// Check the WaveSize attribute is accepted by work graph nodes -// and appears in the metadata +// Check the WaveSize attribute emits diagnostics in a variety of cases. struct INPUT_RECORD { diff --git a/utils/hct/hctdb.py b/utils/hct/hctdb.py index 56788599e2..4bb384b0da 100644 --- a/utils/hct/hctdb.py +++ b/utils/hct/hctdb.py @@ -7665,6 +7665,10 @@ def build_valrules(self): "Sm.WaveSizeNeedsDxil16Plus", "WaveSize is valid only for DXIL version 1.6 and higher.", ) + self.add_valrule( + "Sm.WaveSizeRangeNeedsDxil18Plus", + "WaveSize Range is valid only for DXIL version 1.8 and higher.", + ) self.add_valrule( "Sm.ROVOnlyInPS", "RasterizerOrdered objects are only allowed in 5.0+ pixel shaders.", From a14513bcec2c8e28f48f5c47f4e721bcc1e09959 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Jan 2024 01:32:20 +0000 Subject: [PATCH 06/15] chore: autopublish 2024-01-20T01:32:20Z --- tools/clang/lib/Sema/SemaHLSL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 9d262b5f46..536ddef399 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -12658,7 +12658,7 @@ HLSLWaveSizeAttr *ValidateWaveSizeAttributes(Sema &S, Decl *D, S.Diag(A.getLoc(), diag::err_hlsl_wavesize_pref_size_out_of_range) << (unsigned)prefWave << (unsigned)minWave << (unsigned)maxWave; } - + if (maxWave != 0 && minWave >= maxWave) { S.Diag(A.getLoc(), diag::err_hlsl_wavesize_min_geq_max) << (unsigned)minWave << (unsigned)maxWave; From 79d70a4a26b35832d8e9ab853456da704e8f26af Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 18:41:59 -0800 Subject: [PATCH 07/15] remove degenerate case changes --- tools/clang/lib/Sema/SemaHLSL.cpp | 16 ---------------- .../test/CodeGenHLSL/attributes_wavesize.hlsl | 4 +--- .../validation}/wavesize_range.ll | 2 +- .../validation}/wavesize_range2.ll | 2 +- .../validation}/wavesize_range3.ll | 2 +- .../test/SemaHLSL/ds-error-outputpatch-size.hlsl | 1 - 6 files changed, 4 insertions(+), 23 deletions(-) rename tools/clang/test/{SemaHLSL/attributes => HLSLFileCheck/validation}/wavesize_range.ll (97%) rename tools/clang/test/{SemaHLSL/attributes => HLSLFileCheck/validation}/wavesize_range2.ll (97%) rename tools/clang/test/{SemaHLSL/attributes => HLSLFileCheck/validation}/wavesize_range3.ll (97%) diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 536ddef399..ec92c52df9 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -12629,22 +12629,6 @@ HLSLWaveSizeAttr *ValidateWaveSizeAttributes(Sema &S, Decl *D, int maxWave = pAttr->getMax(); int prefWave = pAttr->getPreferred(); - // canonicalize degenerate cases. - if (maxWave == minWave) { - pAttr->setMax(0); - maxWave = 0; - } - if (maxWave == 0 && prefWave != 0) { - if (prefWave == minWave) { - pAttr->setPreferred(0); - prefWave = 0; - } - else{ - S.Diag(A.getLoc(), diag::err_hlsl_wavesize_pref_size_out_of_range) - << (unsigned)prefWave << (unsigned)minWave << (unsigned)maxWave; - } - } - // validate attribute arguments. if (!DXIL::IsValidWaveSizeValue(minWave, maxWave, prefWave)) { S.Diag(A.getLoc(), diag::err_hlsl_wavesize_size) diff --git a/tools/clang/test/CodeGenHLSL/attributes_wavesize.hlsl b/tools/clang/test/CodeGenHLSL/attributes_wavesize.hlsl index da1c6f4e9c..1a9781291e 100644 --- a/tools/clang/test/CodeGenHLSL/attributes_wavesize.hlsl +++ b/tools/clang/test/CodeGenHLSL/attributes_wavesize.hlsl @@ -1,13 +1,11 @@ -// RUN: %dxc -E main -T cs_6_6 %s | FileCheck %s // RUN: %dxc -E main -T cs_6_6 %s -D WAVESIZE=13 | FileCheck %s -check-prefixes=CHECK-ERR -// RUN: %dxc -E main -T cs_6_6 %s -D WAVESIZE=2 | FileCheck %s -check-prefixes=CHECK-ERR // CHECK: @main, !"main", null, null, [[PROPS:![0-9]+]]} // CHECK: [[PROPS]] = !{i32 4, [[NT:![0-9]+]], i32 11, [[WS:![0-9]+]]} // CHECK: [[NT]] = !{i32 1, i32 1, i32 8} // CHECK: [[WS]] = !{i32 32} -// CHECK-ERR: error: WaveSize value must be between 4 and 128 and a power of 2 +// CHECK-ERR: error: WaveSize arguments must be between 4 and 128 and a power of 2 #ifndef WAVESIZE #define WAVESIZE 32 diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_range.ll b/tools/clang/test/HLSLFileCheck/validation/wavesize_range.ll similarity index 97% rename from tools/clang/test/SemaHLSL/attributes/wavesize_range.ll rename to tools/clang/test/HLSLFileCheck/validation/wavesize_range.ll index 518d3aff48..8de891dfca 100644 --- a/tools/clang/test/SemaHLSL/attributes/wavesize_range.ll +++ b/tools/clang/test/HLSLFileCheck/validation/wavesize_range.ll @@ -1,4 +1,4 @@ -; RUN: %dxv %s | FileCheck %s +; RUN: %dxv %s %dxilver 1.8 | FileCheck %s ; This tests the validator on emitting errors for invalid ; arguments in the wavesize range attribute for entry point functions. diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_range2.ll b/tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll similarity index 97% rename from tools/clang/test/SemaHLSL/attributes/wavesize_range2.ll rename to tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll index e28130295b..20d00bb201 100644 --- a/tools/clang/test/SemaHLSL/attributes/wavesize_range2.ll +++ b/tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll @@ -1,4 +1,4 @@ -; RUN: %dxv %s | FileCheck %s +; RUN: %dxv %s %dxilver 1.8 | FileCheck %s ; This tests the validator on emitting errors for invalid ; arguments in the wavesize range attribute for entry point functions. diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_range3.ll b/tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll similarity index 97% rename from tools/clang/test/SemaHLSL/attributes/wavesize_range3.ll rename to tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll index 97f81979d5..44bd0de09b 100644 --- a/tools/clang/test/SemaHLSL/attributes/wavesize_range3.ll +++ b/tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll @@ -1,4 +1,4 @@ -; RUN: %dxv %s | FileCheck %s +; RUN: %dxv %s %dxilver 1.8 | FileCheck %s ; This tests the validator on emitting errors for invalid ; arguments in the wavesize range attribute for entry point functions. diff --git a/tools/clang/test/SemaHLSL/ds-error-outputpatch-size.hlsl b/tools/clang/test/SemaHLSL/ds-error-outputpatch-size.hlsl index 879063780e..ddc7d2f77c 100644 --- a/tools/clang/test/SemaHLSL/ds-error-outputpatch-size.hlsl +++ b/tools/clang/test/SemaHLSL/ds-error-outputpatch-size.hlsl @@ -1,5 +1,4 @@ // RUN: %dxc -T ds_6_0 -E main -verify %s -// RUN: %dxc -T ds_6_0 -E main -verify %s -spirv struct ControlPoint { float position : MY_BOOL; From 9f7fdbf95ec4e89b67d0ed577c8dd5ed2981983c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Jan 2024 02:44:55 +0000 Subject: [PATCH 08/15] chore: autopublish 2024-01-20T02:44:55Z --- lib/HLSL/DxilValidation.cpp | 4 ++-- tools/clang/lib/Sema/SemaHLSL.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/HLSL/DxilValidation.cpp b/lib/HLSL/DxilValidation.cpp index ba365946a8..bd5e824e53 100644 --- a/lib/HLSL/DxilValidation.cpp +++ b/lib/HLSL/DxilValidation.cpp @@ -5256,8 +5256,8 @@ static void ValidateEntryProps(ValidationContext &ValCtx, if (props.waveMaxSize != 0) { if (DXIL::CompareVersions(ValCtx.m_DxilMajor, ValCtx.m_DxilMinor, 1, 8) < 0) { - ValCtx.EmitFnFormatError(F, ValidationRule::SmWaveSizeRangeNeedsDxil18Plus, - {}); + ValCtx.EmitFnFormatError( + F, ValidationRule::SmWaveSizeRangeNeedsDxil18Plus, {}); } } if (DXIL::CompareVersions(ValCtx.m_DxilMajor, ValCtx.m_DxilMinor, 1, 6) < diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index ec92c52df9..ccd10a0fe3 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -12635,7 +12635,6 @@ HLSLWaveSizeAttr *ValidateWaveSizeAttributes(Sema &S, Decl *D, << DXIL::kMinWaveSize << DXIL::kMaxWaveSize; } - bool prefInRange = prefWave == 0 ? true : prefWave >= minWave && prefWave <= maxWave; if (!prefInRange) { From 6b687c01b3658a40048a3dc1fecd1bcafc2c3097 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 19:07:17 -0800 Subject: [PATCH 09/15] add a test for testing metadata of new wavesize range, fix broken test --- .../test/CodeGenHLSL/attributes_wavesize.hlsl | 12 +++-------- .../test/SemaHLSL/attributes/wavesize_66.hlsl | 7 +++++++ .../attributes/wavesize_range_valid.hlsl | 21 +++++++++++++++++++ .../SemaHLSL/ds-error-outputpatch-size.hlsl | 1 + 4 files changed, 32 insertions(+), 9 deletions(-) create mode 100644 tools/clang/test/SemaHLSL/attributes/wavesize_66.hlsl create mode 100644 tools/clang/test/SemaHLSL/attributes/wavesize_range_valid.hlsl diff --git a/tools/clang/test/CodeGenHLSL/attributes_wavesize.hlsl b/tools/clang/test/CodeGenHLSL/attributes_wavesize.hlsl index 1a9781291e..16e10c1d06 100644 --- a/tools/clang/test/CodeGenHLSL/attributes_wavesize.hlsl +++ b/tools/clang/test/CodeGenHLSL/attributes_wavesize.hlsl @@ -1,17 +1,11 @@ -// RUN: %dxc -E main -T cs_6_6 %s -D WAVESIZE=13 | FileCheck %s -check-prefixes=CHECK-ERR +// RUN: %dxc -E main -T cs_6_6 %s | FileCheck %s // CHECK: @main, !"main", null, null, [[PROPS:![0-9]+]]} // CHECK: [[PROPS]] = !{i32 4, [[NT:![0-9]+]], i32 11, [[WS:![0-9]+]]} // CHECK: [[NT]] = !{i32 1, i32 1, i32 8} // CHECK: [[WS]] = !{i32 32} -// CHECK-ERR: error: WaveSize arguments must be between 4 and 128 and a power of 2 - -#ifndef WAVESIZE -#define WAVESIZE 32 -#endif - -[wavesize(WAVESIZE)] +[wavesize(32)] [numthreads(1,1,8)] void main() { -} \ No newline at end of file +} diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_66.hlsl b/tools/clang/test/SemaHLSL/attributes/wavesize_66.hlsl new file mode 100644 index 0000000000..a8018dcae1 --- /dev/null +++ b/tools/clang/test/SemaHLSL/attributes/wavesize_66.hlsl @@ -0,0 +1,7 @@ +// RUN: %dxc -E main -T cs_6_6 %s -D WAVESIZE=2 -verify +// RUN: %dxc -E main -T cs_6_6 %s -D WAVESIZE=13 -verify + +[wavesize(WAVESIZE)] // expected-error{{WaveSize arguments must be between 4 and 128 and a power of 2}} +[numthreads(1,1,8)] +void main() { +} diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_range_valid.hlsl b/tools/clang/test/SemaHLSL/attributes/wavesize_range_valid.hlsl new file mode 100644 index 0000000000..95ecbd950c --- /dev/null +++ b/tools/clang/test/SemaHLSL/attributes/wavesize_range_valid.hlsl @@ -0,0 +1,21 @@ +// RUN: %dxc -T lib_6_8 %s | FileCheck %s + +// Check the WaveSize attribute emits the right metadata in DXIL + +struct INPUT_RECORD +{ + uint DispatchGrid1 : SV_DispatchGrid; + uint2 a; +}; + + +// CHECK: @node01, !"node01", null, null, [[PROPS:![0-9]+]]} +// CHECK: [[PROPS]] = !{i32 8, i32 15, i32 13, i32 1, i32 23, [[WS:![0-9]+]] +// CHECK: [[WS]] = !{i32 4, i32 16, i32 8} + +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(4, 16, 8)] +void node01(DispatchNodeInputRecord input) { } diff --git a/tools/clang/test/SemaHLSL/ds-error-outputpatch-size.hlsl b/tools/clang/test/SemaHLSL/ds-error-outputpatch-size.hlsl index ddc7d2f77c..879063780e 100644 --- a/tools/clang/test/SemaHLSL/ds-error-outputpatch-size.hlsl +++ b/tools/clang/test/SemaHLSL/ds-error-outputpatch-size.hlsl @@ -1,4 +1,5 @@ // RUN: %dxc -T ds_6_0 -E main -verify %s +// RUN: %dxc -T ds_6_0 -E main -verify %s -spirv struct ControlPoint { float position : MY_BOOL; From 8892782ad142fd959059e9385c692a80af7ef936 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 19:18:02 -0800 Subject: [PATCH 10/15] add positive test that allows for 2 parameters to wavesize range --- .../test/SemaHLSL/attributes/wavesize_range_valid.hlsl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_range_valid.hlsl b/tools/clang/test/SemaHLSL/attributes/wavesize_range_valid.hlsl index 95ecbd950c..56634b25cf 100644 --- a/tools/clang/test/SemaHLSL/attributes/wavesize_range_valid.hlsl +++ b/tools/clang/test/SemaHLSL/attributes/wavesize_range_valid.hlsl @@ -19,3 +19,13 @@ struct INPUT_RECORD [NodeMaxDispatchGrid(32,1,1)] [WaveSize(4, 16, 8)] void node01(DispatchNodeInputRecord input) { } + +// CHECK: @node02, !"node02", null, null, [[PROPS:![0-9]+]]} +// CHECK: [[PROPS]] = !{i32 8, i32 15, i32 13, i32 1, i32 23, [[WS:![0-9]+]] +// CHECK: [[WS]] = !{i32 4, i32 16, i32 0} +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(1,1,1)] +[NodeMaxDispatchGrid(32,1,1)] +[WaveSize(4, 16)] +void node02(DispatchNodeInputRecord input) { } From 57ddb1ca4713e80a0726ab572441a3d1a5db6822 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 19:27:52 -0800 Subject: [PATCH 11/15] fix typo, edit diagnosticsemakinds.td instead of .inc --- lib/DXIL/DxilMetadataHelper.cpp | 2 +- tools/clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 +++++- tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/DXIL/DxilMetadataHelper.cpp b/lib/DXIL/DxilMetadataHelper.cpp index f00e221aea..d3e16d4244 100644 --- a/lib/DXIL/DxilMetadataHelper.cpp +++ b/lib/DXIL/DxilMetadataHelper.cpp @@ -1836,7 +1836,7 @@ void DxilMDHelper::LoadDxilEntryProperties(const MDOperand &MDO, } break; case DxilMDHelper::kDxilRangedWaveSizeTag: { // if we're here, we're using the range variant. - // Extra metadata is used is SM < 6.8 + // Extra metadata is used if SM < 6.8 if (!m_pSM->IsSMAtLeast(6, 8)) m_bExtraMetadata = true; MDNode *pNode = cast(MDO.get()); diff --git a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9993a54ca6..2fce29ea7b 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7483,7 +7483,11 @@ def err_hlsl_profile_conflicts_with_shader_attribute : Error< def err_hlsl_attribute_valid_on_function_only: Error< "attribute is valid only on functions">; def err_hlsl_wavesize_size: Error< - "WaveSize value must be between 4 and 128 and a power of 2">; + "WaveSize arguments must be between 4 and 128 and a power of 2">; +def err_hlsl_wavesize_min_geq_max: Error< + "Minimum WaveSize value %0 must be less than maximum WaveSize value %1">; +def err_hlsl_wavesize_pref_size_out_of_range: Error< + "Preferred WaveSize value %0 must be between %1 and %2">; def err_hlsl_bitfields: Error< "bitfields are not supported in HLSL">; def err_hlsl_bitfields_with_annotation: Error< diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl b/tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl index 20b268cc6a..e611cf24c7 100644 --- a/tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl +++ b/tools/clang/test/SemaHLSL/attributes/wavesize_range.hlsl @@ -23,7 +23,7 @@ void node01(DispatchNodeInputRecord input) { } [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] /* expected-error@+2{{Preferred WaveSize value 32 must be between 16 and 16}} */ -/* expected-error@+1{{Minimum WaveSize value 16 must be less than Maximum WaveSize value 16}} */ +/* expected-error@+1{{Minimum WaveSize value 16 must be less than maximum WaveSize value 16}} */ [WaveSize(16, 16, 32)] void node02(DispatchNodeInputRecord input) { } @@ -31,7 +31,7 @@ void node02(DispatchNodeInputRecord input) { } [NodeLaunch("broadcasting")] [NumThreads(1,1,1)] [NodeMaxDispatchGrid(32,1,1)] -[WaveSize(16, 16, 16)] /* expected-error{{Minimum WaveSize value 16 must be less than Maximum WaveSize value 16}} */ +[WaveSize(16, 16, 16)] /* expected-error{{Minimum WaveSize value 16 must be less than maximum WaveSize value 16}} */ void node03(DispatchNodeInputRecord input) { } // the non-power of 2 diagnostic gets emitted once, regardless of how many arguments aren't powers of 2. From 2d42e75a123d5a9b36513538215098b5c80d3209 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 19:34:26 -0800 Subject: [PATCH 12/15] clean up comments --- tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll | 4 ++-- tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll b/tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll index 20d00bb201..ea6d9a1647 100644 --- a/tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll +++ b/tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll @@ -2,8 +2,8 @@ ; This tests the validator on emitting errors for invalid ; arguments in the wavesize range attribute for entry point functions. -; This test tests that when the preferred value lies outside of the given -; minimum and maximum value range, an error is emitted. +; This test tests that when the Minimum wavesize value is equal to the Maximum +; wavesize value, a diagnostic is emitted. ; shader hash: e935848c1a904483af91f615705c305c ; diff --git a/tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll b/tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll index 44bd0de09b..4ff3c7721d 100644 --- a/tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll +++ b/tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll @@ -2,8 +2,8 @@ ; This tests the validator on emitting errors for invalid ; arguments in the wavesize range attribute for entry point functions. -; This test tests that when the preferred value lies outside of the given -; minimum and maximum value range, an error is emitted. +; This test tests that when a wavesize argument is not valid +; (in this case, not a power of 2), a diagnostic is emitted ; shader hash: e935848c1a904483af91f615705c305c ; From bf88b5d8123e4e5483df4da374714ba6a5055a8f Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 19:44:47 -0800 Subject: [PATCH 13/15] add Chris's entry diag patch, fix run lines --- tools/clang/include/clang/Basic/Attr.td | 8 ++++++++ tools/clang/lib/Sema/SemaHLSL.cpp | 5 +++++ .../attributes/wavesize_range_valid.hlsl | 0 .../validation/wavesize_range.ll | 2 +- .../validation/wavesize_range2.ll | 2 +- .../validation/wavesize_range3.ll | 2 +- .../test/SemaHLSL/attributes/wavesize_66.hlsl | 6 ++++++ .../attributes/wavesize_range_lib_6_6.hlsl | 19 +++++++++++++++++++ 8 files changed, 41 insertions(+), 3 deletions(-) rename tools/clang/test/{SemaHLSL => HLSLFileCheck/hlsl/entry}/attributes/wavesize_range_valid.hlsl (100%) create mode 100644 tools/clang/test/SemaHLSL/attributes/wavesize_range_lib_6_6.hlsl diff --git a/tools/clang/include/clang/Basic/Attr.td b/tools/clang/include/clang/Basic/Attr.td index c6480c8c8a..0157bac272 100644 --- a/tools/clang/include/clang/Basic/Attr.td +++ b/tools/clang/include/clang/Basic/Attr.td @@ -910,6 +910,14 @@ def HLSLWaveSize : InheritableAttr { let Spellings = [CXX11<"", "wavesize", 2017>]; let Args = [IntArgument<"Min">, DefaultIntArgument<"Max", 0>, DefaultIntArgument<"Preferred", 0>]; let Documentation = [Undocumented]; + + let AdditionalMembers = [{ + private: + int SpelledArgsCount = 0; + public: + int getSpelledArgsCount() const { return SpelledArgsCount; } + void setSpelledArgsCount(int C) { SpelledArgsCount = C; } + }]; } def HLSLWaveOpsIncludeHelperLanes : InheritableAttr { diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index ccd10a0fe3..7531f968de 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -12625,6 +12625,7 @@ HLSLWaveSizeAttr *ValidateWaveSizeAttributes(Sema &S, Decl *D, ValidateAttributeIntArg(S, A, 1), ValidateAttributeIntArg(S, A, 2), A.getAttributeSpellingListIndex()); + pAttr->setSpelledArgsCount(A.getNumArgs()); int minWave = pAttr->getMin(); int maxWave = pAttr->getMax(); int prefWave = pAttr->getPreferred(); @@ -15218,6 +15219,10 @@ void DiagnoseComputeEntry(Sema &S, FunctionDecl *FD, llvm::StringRef StageName, << "wavesize" << "6.6"; } + if (!SM->IsSM68Plus() && WaveSizeAttr->getSpelledArgsCount() > 1) + S.Diags.Report(WaveSizeAttr->getRange().getBegin(), + diag::err_attribute_too_many_arguments) + << "wavesize" << 1; } } } diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_range_valid.hlsl b/tools/clang/test/HLSLFileCheck/hlsl/entry/attributes/wavesize_range_valid.hlsl similarity index 100% rename from tools/clang/test/SemaHLSL/attributes/wavesize_range_valid.hlsl rename to tools/clang/test/HLSLFileCheck/hlsl/entry/attributes/wavesize_range_valid.hlsl diff --git a/tools/clang/test/HLSLFileCheck/validation/wavesize_range.ll b/tools/clang/test/HLSLFileCheck/validation/wavesize_range.ll index 8de891dfca..f5046d8b2c 100644 --- a/tools/clang/test/HLSLFileCheck/validation/wavesize_range.ll +++ b/tools/clang/test/HLSLFileCheck/validation/wavesize_range.ll @@ -1,4 +1,4 @@ -; RUN: %dxv %s %dxilver 1.8 | FileCheck %s +; RUN: %dxilver 1.8 | %dxv %s | FileCheck %s ; This tests the validator on emitting errors for invalid ; arguments in the wavesize range attribute for entry point functions. diff --git a/tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll b/tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll index ea6d9a1647..53621fd184 100644 --- a/tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll +++ b/tools/clang/test/HLSLFileCheck/validation/wavesize_range2.ll @@ -1,4 +1,4 @@ -; RUN: %dxv %s %dxilver 1.8 | FileCheck %s +; RUN: %dxilver 1.8 | %dxv %s | FileCheck %s ; This tests the validator on emitting errors for invalid ; arguments in the wavesize range attribute for entry point functions. diff --git a/tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll b/tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll index 4ff3c7721d..27e128244f 100644 --- a/tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll +++ b/tools/clang/test/HLSLFileCheck/validation/wavesize_range3.ll @@ -1,4 +1,4 @@ -; RUN: %dxv %s %dxilver 1.8 | FileCheck %s +; RUN: %dxilver 1.8 | %dxv %s | FileCheck %s ; This tests the validator on emitting errors for invalid ; arguments in the wavesize range attribute for entry point functions. diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_66.hlsl b/tools/clang/test/SemaHLSL/attributes/wavesize_66.hlsl index a8018dcae1..e3e2f2a3cc 100644 --- a/tools/clang/test/SemaHLSL/attributes/wavesize_66.hlsl +++ b/tools/clang/test/SemaHLSL/attributes/wavesize_66.hlsl @@ -5,3 +5,9 @@ [numthreads(1,1,8)] void main() { } + + +[wavesize(4, 8)] // No diagnostic expected for inactive entry +[numthreads(1,1,8)] +void inactive() { +} diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_range_lib_6_6.hlsl b/tools/clang/test/SemaHLSL/attributes/wavesize_range_lib_6_6.hlsl new file mode 100644 index 0000000000..713bd1c724 --- /dev/null +++ b/tools/clang/test/SemaHLSL/attributes/wavesize_range_lib_6_6.hlsl @@ -0,0 +1,19 @@ +// RUN: %dxc -E main -T lib_6_6 %s -verify + +[wavesize(4)] +[numthreads(1,1,8)] +[shader("compute")] +void one() { +} + +[wavesize(4, 8)] // expected-error{{wavesize attribute takes no more than 1 argument}} +[numthreads(1,1,8)] +[shader("compute")] +void two() { +} + +[wavesize(4,8, 8)] // expected-error{{wavesize attribute takes no more than 1 argument}} +[numthreads(1,1,8)] +[shader("compute")] +void three() { +} From 1623f9afbf0d46b2a0a082ba3e2dc22366394668 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 19 Jan 2024 20:02:15 -0800 Subject: [PATCH 14/15] update error message, add diag that catches when multiple args are in wavesize for sm < 6.8 --- tools/clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ tools/clang/lib/Sema/SemaHLSL.cpp | 2 +- .../test/SemaHLSL/attributes/wavesize_range_lib_6_6.hlsl | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index 2fce29ea7b..932cdd2c5f 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7488,6 +7488,8 @@ def err_hlsl_wavesize_min_geq_max: Error< "Minimum WaveSize value %0 must be less than maximum WaveSize value %1">; def err_hlsl_wavesize_pref_size_out_of_range: Error< "Preferred WaveSize value %0 must be between %1 and %2">; +def err_hlsl_wavesize_insufficient_shader_model: Error< + "WaveSize only takes multiple arguments in Shader Model 6.8 or higher">; def err_hlsl_bitfields: Error< "bitfields are not supported in HLSL">; def err_hlsl_bitfields_with_annotation: Error< diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 7531f968de..819b8b1d58 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -15221,7 +15221,7 @@ void DiagnoseComputeEntry(Sema &S, FunctionDecl *FD, llvm::StringRef StageName, } if (!SM->IsSM68Plus() && WaveSizeAttr->getSpelledArgsCount() > 1) S.Diags.Report(WaveSizeAttr->getRange().getBegin(), - diag::err_attribute_too_many_arguments) + diag::err_hlsl_wavesize_insufficient_shader_model) << "wavesize" << 1; } } diff --git a/tools/clang/test/SemaHLSL/attributes/wavesize_range_lib_6_6.hlsl b/tools/clang/test/SemaHLSL/attributes/wavesize_range_lib_6_6.hlsl index 713bd1c724..059061782c 100644 --- a/tools/clang/test/SemaHLSL/attributes/wavesize_range_lib_6_6.hlsl +++ b/tools/clang/test/SemaHLSL/attributes/wavesize_range_lib_6_6.hlsl @@ -6,13 +6,13 @@ void one() { } -[wavesize(4, 8)] // expected-error{{wavesize attribute takes no more than 1 argument}} +[wavesize(4, 8)] // expected-error{{WaveSize only takes multiple arguments in Shader Model 6.8 or higher}} [numthreads(1,1,8)] [shader("compute")] void two() { } -[wavesize(4,8, 8)] // expected-error{{wavesize attribute takes no more than 1 argument}} +[wavesize(4,8, 8)] // expected-error{{WaveSize only takes multiple arguments in Shader Model 6.8 or higher}} [numthreads(1,1,8)] [shader("compute")] void three() { From 2e43a3a488b2184762933aa9cf9e3d49106eae84 Mon Sep 17 00:00:00 2001 From: Greg Roth Date: Fri, 19 Jan 2024 20:40:38 -0800 Subject: [PATCH 15/15] Correct whitespace at end of lines --- utils/hct/hctdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/hct/hctdb.py b/utils/hct/hctdb.py index 4bb384b0da..2aaf3b8457 100644 --- a/utils/hct/hctdb.py +++ b/utils/hct/hctdb.py @@ -7652,7 +7652,7 @@ def build_valrules(self): self.add_valrule( "Sm.WaveSizeValue", "Declared WaveSize %0 outside valid range [%1..%2], or not a power of 2.", - ) + ) self.add_valrule( "Sm.WaveSizePreferredOutOfRange", "Preferred WaveSize %0 outside valid range [%1..%2]", @@ -7668,7 +7668,7 @@ def build_valrules(self): self.add_valrule( "Sm.WaveSizeRangeNeedsDxil18Plus", "WaveSize Range is valid only for DXIL version 1.8 and higher.", - ) + ) self.add_valrule( "Sm.ROVOnlyInPS", "RasterizerOrdered objects are only allowed in 5.0+ pixel shaders.",