diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index f74c9775cb3f3..355a86420d29d 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -214,6 +214,39 @@ enum class ShaderVisibility : uint32_t { #include "DXContainerConstants.def" }; +inline dxil::ResourceClass +toResourceClass(dxbc::DescriptorRangeType RangeType) { + using namespace dxbc; + switch (RangeType) { + case DescriptorRangeType::SRV: + return dxil::ResourceClass::SRV; + case DescriptorRangeType::UAV: + return dxil::ResourceClass::UAV; + case DescriptorRangeType::CBV: + return dxil::ResourceClass::CBuffer; + case DescriptorRangeType::Sampler: + return dxil::ResourceClass::Sampler; + } + llvm_unreachable("Unknown DescriptorRangeType"); +} + +inline dxil::ResourceClass toResourceClass(dxbc::RootParameterType Type) { + using namespace dxbc; + switch (Type) { + case RootParameterType::Constants32Bit: + return dxil::ResourceClass::CBuffer; + case RootParameterType::SRV: + return dxil::ResourceClass::SRV; + case RootParameterType::UAV: + return dxil::ResourceClass::UAV; + case RootParameterType::CBV: + return dxil::ResourceClass::CBuffer; + case dxbc::RootParameterType::DescriptorTable: + llvm_unreachable("DescriptorTable is not convertible to ResourceClass"); + } + llvm_unreachable("Unknown RootParameterType"); +} + LLVM_ABI ArrayRef> getShaderVisibility(); #define SHADER_VISIBILITY(Val, Enum) \ diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h index c6d7c32c4ad95..096cd9dded9eb 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h @@ -48,6 +48,51 @@ class RootSignatureValidationError } }; +class TableRegisterOverflowError + : public ErrorInfo { +public: + static char ID; + dxbc::DescriptorRangeType Type; + uint32_t Register; + uint32_t Space; + + TableRegisterOverflowError(dxbc::DescriptorRangeType Type, uint32_t Register, + uint32_t Space) + : Type(Type), Register(Register), Space(Space) {} + + void log(raw_ostream &OS) const override { + OS << "Cannot append range with implicit lower bound after an unbounded " + "range " + << getResourceClassName(toResourceClass(Type)) + << "(register=" << Register << ", space=" << Space << ")."; + } + + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } +}; + +class TableSamplerMixinError : public ErrorInfo { +public: + static char ID; + dxbc::DescriptorRangeType Type; + uint32_t Location; + + TableSamplerMixinError(dxbc::DescriptorRangeType Type, uint32_t Location) + : Type(Type), Location(Location) {} + + void log(raw_ostream &OS) const override { + OS << "Samplers cannot be mixed with other " + << "resource types in a descriptor table, " + << getResourceClassName(toResourceClass(Type)) + << "(location=" << Location << ")"; + } + + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } +}; + class GenericRSMetadataError : public ErrorInfo { public: LLVM_ABI static char ID; diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index fde32a1fff591..c6a2886e89118 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -40,6 +40,9 @@ LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); LLVM_ABI bool verifyComparisonFunc(uint32_t ComparisonFunc); LLVM_ABI bool verifyBorderColor(uint32_t BorderColor); LLVM_ABI bool verifyLOD(float LOD); +LLVM_ABI bool verifyOffsetOverflowing( + uint64_t &AppendingRegister, uint32_t OffsetInDescriptorsFromTableStart, + uint32_t BaseRegister, uint32_t Space, uint32_t NumDescriptors); } // namespace rootsig } // namespace hlsl diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 157bfc665b207..40b1f10e09ae9 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -26,6 +26,8 @@ namespace rootsig { char GenericRSMetadataError::ID; char InvalidRSMetadataFormat::ID; char InvalidRSMetadataValue::ID; +char TableSamplerMixinError::ID; +char TableRegisterOverflowError::ID; template char RootSignatureValidationError::ID; static std::optional extractMdIntValue(MDNode *Node, @@ -513,6 +515,48 @@ Error MetadataParser::parseRootSignatureElement(mcdxbc::RootSignatureDesc &RSD, llvm_unreachable("Unhandled RootSignatureElementKind enum."); } +Error validateDescriptorTableSamplerMixin(mcdxbc::DescriptorTable Table, + uint32_t Location) { + bool HasSampler = false; + bool HasOtherRangeType = false; + dxbc::DescriptorRangeType OtherRangeType; + + for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { + dxbc::DescriptorRangeType RangeType = + static_cast(Range.RangeType); + + if (RangeType == dxbc::DescriptorRangeType::Sampler) { + HasSampler = true; + } else { + HasOtherRangeType = true; + OtherRangeType = RangeType; + } + } + + // Samplers cannot be mixed with other resources in a descriptor table. + if (HasSampler && HasOtherRangeType) + return make_error(OtherRangeType, Location); + return Error::success(); +} + +Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, + uint32_t Location) { + uint64_t AppendingRegister = 0; + + for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { + dxbc::DescriptorRangeType RangeType = + static_cast(Range.RangeType); + if (verifyOffsetOverflowing(AppendingRegister, + Range.OffsetInDescriptorsFromTableStart, + Range.BaseShaderRegister, Range.RegisterSpace, + Range.NumDescriptors)) + return make_error( + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + } + + return Error::success(); +} + Error MetadataParser::validateRootSignature( const mcdxbc::RootSignatureDesc &RSD) { Error DeferredErrs = Error::success(); @@ -597,6 +641,16 @@ Error MetadataParser::validateRootSignature( joinErrors(std::move(DeferredErrs), make_error>( "DescriptorFlag", Range.Flags)); + + if (Error Err = + validateDescriptorTableSamplerMixin(Table, Info.Location)) { + DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err)); + } + + if (Error Err = + validateDescriptorTableRegisterOverflow(Table, Info.Location)) { + DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err)); + } } break; } diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 72308a3de5fd4..52cada81a7c44 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -180,6 +180,48 @@ bool verifyBorderColor(uint32_t BorderColor) { bool verifyLOD(float LOD) { return !std::isnan(LOD); } +/** This validation logic was extracted from the DXC codebase + * https://github.com/microsoft/DirectXShaderCompiler/blob/7a1b1df9b50a8350a63756720e85196e0285e664/lib/DxilRootSignature/DxilRootSignatureValidator.cpp#L205 + * + * It checks if the registers in a descriptor table are overflowing, meaning, + * they are trying to bind a register larger than MAX_UINT. + * This will usually happen when the descriptor table appends a resource + * after an unbounded range. + **/ +bool verifyOffsetOverflowing(uint64_t &AppendingRegister, + uint32_t OffsetInDescriptorsFromTableStart, + uint32_t BaseRegister, uint32_t Space, + uint32_t NumDescriptors) { + uint64_t Register = AppendingRegister; + + // Checks if the current register should be appended to the previous range. + if (OffsetInDescriptorsFromTableStart != ~0U) + Register = OffsetInDescriptorsFromTableStart; + + // Check for overflow in the register value. + if (Register > ~0U) + return true; + // Is the current range unbounded? + if (NumDescriptors == ~0U) { + // No ranges should be appended to an unbounded range. + AppendingRegister = (uint64_t)~0U + (uint64_t)1ULL; + } else { + // Is the defined range, overflowing? + uint64_t UpperBound = + (uint64_t)BaseRegister + (uint64_t)NumDescriptors - (uint64_t)1U; + if (UpperBound > ~0U) + return true; + + // If we append this range, will it overflow? + uint64_t AppendingUpperBound = + (uint64_t)Register + (uint64_t)NumDescriptors - (uint64_t)1U; + if (AppendingUpperBound > ~0U) + return true; + AppendingRegister = Register + NumDescriptors; + } + return false; +} + } // namespace rootsig } // namespace hlsl } // namespace llvm diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 2f2db23cb2be5..1d2c9a35c1184 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -25,38 +25,6 @@ using namespace llvm; using namespace llvm::dxil; -static ResourceClass toResourceClass(dxbc::DescriptorRangeType RangeType) { - using namespace dxbc; - switch (RangeType) { - case DescriptorRangeType::SRV: - return ResourceClass::SRV; - case DescriptorRangeType::UAV: - return ResourceClass::UAV; - case DescriptorRangeType::CBV: - return ResourceClass::CBuffer; - case DescriptorRangeType::Sampler: - return ResourceClass::Sampler; - } - llvm_unreachable("Unknown DescriptorRangeType"); -} - -static ResourceClass toResourceClass(dxbc::RootParameterType Type) { - using namespace dxbc; - switch (Type) { - case RootParameterType::Constants32Bit: - return ResourceClass::CBuffer; - case RootParameterType::SRV: - return ResourceClass::SRV; - case RootParameterType::UAV: - return ResourceClass::UAV; - case RootParameterType::CBV: - return ResourceClass::CBuffer; - case dxbc::RootParameterType::DescriptorTable: - llvm_unreachable("DescriptorTable is not convertible to ResourceClass"); - } - llvm_unreachable("Unknown RootParameterType"); -} - static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) { for (const auto &UAV : DRM.uavs()) { if (UAV.CounterDirection != ResourceCounterDirection::Invalid) @@ -237,10 +205,10 @@ getRootDescriptorsBindingInfo(const mcdxbc::RootSignatureDesc &RSD, return RDs; } -static void validateRootSignature(Module &M, - const mcdxbc::RootSignatureDesc &RSD, - dxil::ModuleMetadataInfo &MMI, - DXILResourceMap &DRM) { +static void validateRootSignatureBindings(Module &M, + const mcdxbc::RootSignatureDesc &RSD, + dxil::ModuleMetadataInfo &MMI, + DXILResourceMap &DRM) { hlsl::BindingInfoBuilder Builder; dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile); @@ -268,10 +236,11 @@ static void validateRootSignature(Module &M, case dxbc::RootParameterType::CBV: { dxbc::RTS0::v2::RootDescriptor Desc = RSD.ParametersContainer.getRootDescriptor(ParamInfo.Location); - Builder.trackBinding(toResourceClass(static_cast( - ParamInfo.Header.ParameterType)), - Desc.RegisterSpace, Desc.ShaderRegister, - Desc.ShaderRegister, &ParamInfo); + Builder.trackBinding( + dxbc::toResourceClass(static_cast( + ParamInfo.Header.ParameterType)), + Desc.RegisterSpace, Desc.ShaderRegister, Desc.ShaderRegister, + &ParamInfo); break; } @@ -285,7 +254,7 @@ static void validateRootSignature(Module &M, ? Range.BaseShaderRegister : Range.BaseShaderRegister + Range.NumDescriptors - 1; Builder.trackBinding( - toResourceClass( + dxbc::toResourceClass( static_cast(Range.RangeType)), Range.RegisterSpace, Range.BaseShaderRegister, UpperBound, &ParamInfo); @@ -346,8 +315,9 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in " "DXILResourceImplicitBinding pass"); - if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI)) - validateRootSignature(M, *RSD, MMI, DRM); + if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI)) { + validateRootSignatureBindings(M, *RSD, MMI, DRM); + } } PreservedAnalyses diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll index 8eb7f90c6b757..a489f5cd6638f 100644 --- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll @@ -11,8 +11,9 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } !dx.rootsignatures = !{!2} ; list of function/root signature pairs !2 = !{ ptr @main, !3, i32 2 } ; function, root signature -!3 = !{ !5 } ; list of root signature elements -!5 = !{ !"DescriptorTable", i32 0, !6, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20 } +!3 = !{ !5, !21 } ; list of root signature elements +!5 = !{ !"DescriptorTable", i32 0, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20 } +!21 = !{ !"DescriptorTable", i32 0,!6, !8, !9 } ; typedef enum D3D12_DESCRIPTOR_RANGE_FLAGS { ; NONE = 0, @@ -53,105 +54,111 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } !20 = !{ !"UAV", i32 5, i32 1, i32 15, i32 5, i32 65540 } ;DXC:- Name: RTS0 -;DXC-NEXT: Size: 380 -;DXC-NEXT: RootSignature: -;DXC-NEXT: Version: 2 -;DXC-NEXT: NumRootParameters: 1 -;DXC-NEXT: RootParametersOffset: 24 -;DXC-NEXT: NumStaticSamplers: 0 -;DXC-NEXT: StaticSamplersOffset: 0 -;DXC-NEXT: Parameters: -;DXC-NEXT: - ParameterType: 0 -;DXC-NEXT: ShaderVisibility: 0 -;DXC-NEXT: Table: -;DXC-NEXT: NumRanges: 14 -;DXC-NEXT: RangesOffset: 44 -;DXC-NEXT: Ranges: -;DXC-NEXT: - RangeType: 3 -;DXC-NEXT: NumDescriptors: 1 -;DXC-NEXT: BaseShaderRegister: 0 -;DXC-NEXT: RegisterSpace: 1 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 -;DXC-NEXT: - RangeType: 3 -;DXC-NEXT: NumDescriptors: 1 -;DXC-NEXT: BaseShaderRegister: 0 -;DXC-NEXT: RegisterSpace: 3 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 -;DXC-NEXT: DESCRIPTORS_VOLATILE: true -;DXC-NEXT: - RangeType: 3 -;DXC-NEXT: NumDescriptors: 1 -;DXC-NEXT: BaseShaderRegister: 0 -;DXC-NEXT: RegisterSpace: 4 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 -;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true -;DXC-NEXT: - RangeType: 0 -;DXC-NEXT: NumDescriptors: 1 -;DXC-NEXT: BaseShaderRegister: 0 -;DXC-NEXT: RegisterSpace: 5 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 -;DXC-NEXT: DESCRIPTORS_VOLATILE: true -;DXC-NEXT: - RangeType: 1 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 6 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DESCRIPTORS_VOLATILE: true -;DXC-NEXT: - RangeType: 2 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 7 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_VOLATILE: true -;DXC-NEXT: - RangeType: 0 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 8 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_STATIC: true -;DXC-NEXT: - RangeType: 1 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 9 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true -;DXC-NEXT: - RangeType: 2 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 10 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DESCRIPTORS_VOLATILE: true -;DXC-NEXT: DATA_VOLATILE: true -;DXC-NEXT: - RangeType: 0 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 11 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DESCRIPTORS_VOLATILE: true -;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true -;DXC-NEXT: - RangeType: 1 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 12 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true -;DXC-NEXT: - RangeType: 2 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 13 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_VOLATILE: true -;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true -;DXC-NEXT: - RangeType: 0 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 14 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_STATIC: true -;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true -;DXC-NEXT: - RangeType: 1 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 15 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true -;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true +;DXC-NEXT: Size: 400 +;DXC-NEXT: RootSignature: +;DXC-NEXT: Version: 2 +;DXC-NEXT: NumRootParameters: 2 +;DXC-NEXT: RootParametersOffset: 24 +;DXC-NEXT: NumStaticSamplers: 0 +;DXC-NEXT: StaticSamplersOffset: 0 +;DXC-NEXT: Parameters: +;DXC-NEXT: - ParameterType: 0 +;DXC-NEXT: ShaderVisibility: 0 +;DXC-NEXT: Table: +;DXC-NEXT: NumRanges: 11 +;DXC-NEXT: RangesOffset: 56 +;DXC-NEXT: Ranges: +;DXC-NEXT: - RangeType: 0 +;DXC-NEXT: NumDescriptors: 1 +;DXC-NEXT: BaseShaderRegister: 0 +;DXC-NEXT: RegisterSpace: 5 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 +;DXC-NEXT: DESCRIPTORS_VOLATILE: true +;DXC-NEXT: - RangeType: 1 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 6 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DESCRIPTORS_VOLATILE: true +;DXC-NEXT: - RangeType: 2 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 7 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_VOLATILE: true +;DXC-NEXT: - RangeType: 0 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 8 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_STATIC: true +;DXC-NEXT: - RangeType: 1 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 9 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true +;DXC-NEXT: - RangeType: 2 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 10 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DESCRIPTORS_VOLATILE: true +;DXC-NEXT: DATA_VOLATILE: true +;DXC-NEXT: - RangeType: 0 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 11 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DESCRIPTORS_VOLATILE: true +;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true +;DXC-NEXT: - RangeType: 1 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 12 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true +;DXC-NEXT: - RangeType: 2 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 13 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_VOLATILE: true +;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true +;DXC-NEXT: - RangeType: 0 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 14 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_STATIC: true +;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true +;DXC-NEXT: - RangeType: 1 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 15 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true +;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true +;DXC-NEXT: - ParameterType: 0 +;DXC-NEXT: ShaderVisibility: 0 +;DXC-NEXT: Table: +;DXC-NEXT: NumRanges: 3 +;DXC-NEXT: RangesOffset: 328 +;DXC-NEXT: Ranges: +;DXC-NEXT: - RangeType: 3 +;DXC-NEXT: NumDescriptors: 1 +;DXC-NEXT: BaseShaderRegister: 0 +;DXC-NEXT: RegisterSpace: 1 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 +;DXC-NEXT: - RangeType: 3 +;DXC-NEXT: NumDescriptors: 1 +;DXC-NEXT: BaseShaderRegister: 0 +;DXC-NEXT: RegisterSpace: 3 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 +;DXC-NEXT: DESCRIPTORS_VOLATILE: true +;DXC-NEXT: - RangeType: 3 +;DXC-NEXT: NumDescriptors: 1 +;DXC-NEXT: BaseShaderRegister: 0 +;DXC-NEXT: RegisterSpace: 4 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 +;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll index 053721de1eb1f..1333f5d290e4b 100644 --- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll @@ -11,34 +11,41 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } !dx.rootsignatures = !{!2} ; list of function/root signature pairs !2 = !{ ptr @main, !3, i32 1 } ; function, root signature -!3 = !{ !5 } ; list of root signature elements -!5 = !{ !"DescriptorTable", i32 0, !6, !7 } +!3 = !{ !5, !8 } ; list of root signature elements +!5 = !{ !"DescriptorTable", i32 0, !6 } !6 = !{ !"Sampler", i32 1, i32 1, i32 0, i32 -1, i32 1 } +!8 = !{ !"DescriptorTable", i32 0, !7 } !7 = !{ !"UAV", i32 5, i32 1, i32 10, i32 5, i32 3 } ; DXC: - Name: RTS0 -; DXC-NEXT: Size: 84 -; DXC-NEXT: RootSignature: -; DXC-NEXT: Version: 1 -; DXC-NEXT: NumRootParameters: 1 -; DXC-NEXT: RootParametersOffset: 24 -; DXC-NEXT: NumStaticSamplers: 0 -; DXC-NEXT: StaticSamplersOffset: 0 -; DXC-NEXT: Parameters: -; DXC-NEXT: - ParameterType: 0 -; DXC-NEXT: ShaderVisibility: 0 -; DXC-NEXT: Table: -; DXC-NEXT: NumRanges: 2 -; DXC-NEXT: RangesOffset: 44 -; DXC-NEXT: Ranges: -; DXC-NEXT: - RangeType: 3 -; DXC-NEXT: NumDescriptors: 1 -; DXC-NEXT: BaseShaderRegister: 1 -; DXC-NEXT: RegisterSpace: 0 -; DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 -; DXC-NEXT: - RangeType: 1 -; DXC-NEXT: NumDescriptors: 5 -; DXC-NEXT: BaseShaderRegister: 1 -; DXC-NEXT: RegisterSpace: 10 -; DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: Size: 104 +;DXC-NEXT: RootSignature: +;DXC-NEXT: Version: 1 +;DXC-NEXT: NumRootParameters: 2 +;DXC-NEXT: RootParametersOffset: 24 +;DXC-NEXT: NumStaticSamplers: 0 +;DXC-NEXT: StaticSamplersOffset: 0 +;DXC-NEXT: Parameters: +;DXC-NEXT: - ParameterType: 0 +;DXC-NEXT: ShaderVisibility: 0 +;DXC-NEXT: Table: +;DXC-NEXT: NumRanges: 1 +;DXC-NEXT: RangesOffset: 56 +;DXC-NEXT: Ranges: +;DXC-NEXT: - RangeType: 3 +;DXC-NEXT: NumDescriptors: 1 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 0 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 +;DXC-NEXT: - ParameterType: 0 +;DXC-NEXT: ShaderVisibility: 0 +;DXC-NEXT: Table: +;DXC-NEXT: NumRanges: 1 +;DXC-NEXT: RangesOffset: 84 +;DXC-NEXT: Ranges: +;DXC-NEXT: - RangeType: 1 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 10 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll new file mode 100644 index 0000000000000..2b5ce4f52b94e --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll @@ -0,0 +1,19 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s +; This test check if a resource is implicitly overflowing. That means, it is appending a resource after an unbounded range. + +; CHECK: error: Cannot append range with implicit lower bound after an unbounded range UAV(register=0, space=0). + +@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!3} +!3 = !{!"DescriptorTable", i32 0, !4, !5} +!4 = !{!"UAV", i32 -1, i32 1, i32 0, i32 2, i32 0} +!5 = !{!"UAV", i32 1, i32 0, i32 0, i32 -1, i32 0} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll new file mode 100644 index 0000000000000..65542a6ca98f2 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll @@ -0,0 +1,15 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s +; CHECK: error: Cannot append range with implicit lower bound after an unbounded range UAV(register=4294967295, space=0). +@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!3} +!3 = !{!"DescriptorTable", i32 0, !4} +!4 = !{!"UAV", i32 100, i32 4294967295, i32 0, i32 -1, i32 0} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll new file mode 100644 index 0000000000000..d4caeb2675d82 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll @@ -0,0 +1,18 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s +; CHECK: error: Samplers cannot be mixed with other resource types in a descriptor table, UAV(location=0) + +@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!3} +!3 = !{!"DescriptorTable", i32 0, !4, !5} +!4 = !{!"UAV", i32 1, i32 0, i32 0, i32 -1, i32 0} +!5 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0} +