-
Notifications
You must be signed in to change notification settings - Fork 14.2k
[DirectX] Add static sampler support to root signature #143422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/joaosaffran/142492
Are you sure you want to change the base?
[DirectX] Add static sampler support to root signature #143422
Conversation
@llvm/pr-subscribers-backend-directx Author: None (joaosaffran) ChangesThis patch introduces the following changes to the DirectX container implementation:
Testing:
Patch is 32.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143422.diff 17 Files Affected:
diff --git a/llvm/lib/MC/DXContainerRootSignature.cpp b/llvm/lib/MC/DXContainerRootSignature.cpp
index 6c71823a51f85..77d648a739b87 100644
--- a/llvm/lib/MC/DXContainerRootSignature.cpp
+++ b/llvm/lib/MC/DXContainerRootSignature.cpp
@@ -71,12 +71,16 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
BOS.reserveExtraSpace(getSize());
const uint32_t NumParameters = ParametersContainer.size();
-
+ const uint32_t NumSamplers = StaticSamplers.size();
support::endian::write(BOS, Version, llvm::endianness::little);
support::endian::write(BOS, NumParameters, llvm::endianness::little);
support::endian::write(BOS, RootParameterOffset, llvm::endianness::little);
- support::endian::write(BOS, NumStaticSamplers, llvm::endianness::little);
- support::endian::write(BOS, StaticSamplersOffset, llvm::endianness::little);
+ support::endian::write(BOS, NumSamplers, llvm::endianness::little);
+ uint32_t SSO = StaticSamplersOffset;
+ if (NumSamplers > 0)
+ SSO = writePlaceholder(BOS);
+ else
+ support::endian::write(BOS, SSO, llvm::endianness::little);
support::endian::write(BOS, Flags, llvm::endianness::little);
SmallVector<uint32_t> ParamsOffsets;
@@ -142,20 +146,23 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
}
}
}
- for (const auto &S : StaticSamplers) {
- support::endian::write(BOS, S.Filter, llvm::endianness::little);
- support::endian::write(BOS, S.AddressU, llvm::endianness::little);
- support::endian::write(BOS, S.AddressV, llvm::endianness::little);
- support::endian::write(BOS, S.AddressW, llvm::endianness::little);
- support::endian::write(BOS, S.MipLODBias, llvm::endianness::little);
- support::endian::write(BOS, S.MaxAnisotropy, llvm::endianness::little);
- support::endian::write(BOS, S.ComparisonFunc, llvm::endianness::little);
- support::endian::write(BOS, S.BorderColor, llvm::endianness::little);
- support::endian::write(BOS, S.MinLOD, llvm::endianness::little);
- support::endian::write(BOS, S.MaxLOD, llvm::endianness::little);
- support::endian::write(BOS, S.ShaderRegister, llvm::endianness::little);
- support::endian::write(BOS, S.RegisterSpace, llvm::endianness::little);
- support::endian::write(BOS, S.ShaderVisibility, llvm::endianness::little);
+ if (NumSamplers > 0) {
+ rewriteOffsetToCurrentByte(BOS, SSO);
+ for (const auto &S : StaticSamplers) {
+ support::endian::write(BOS, S.Filter, llvm::endianness::little);
+ support::endian::write(BOS, S.AddressU, llvm::endianness::little);
+ support::endian::write(BOS, S.AddressV, llvm::endianness::little);
+ support::endian::write(BOS, S.AddressW, llvm::endianness::little);
+ support::endian::write(BOS, S.MipLODBias, llvm::endianness::little);
+ support::endian::write(BOS, S.MaxAnisotropy, llvm::endianness::little);
+ support::endian::write(BOS, S.ComparisonFunc, llvm::endianness::little);
+ support::endian::write(BOS, S.BorderColor, llvm::endianness::little);
+ support::endian::write(BOS, S.MinLOD, llvm::endianness::little);
+ support::endian::write(BOS, S.MaxLOD, llvm::endianness::little);
+ support::endian::write(BOS, S.ShaderRegister, llvm::endianness::little);
+ support::endian::write(BOS, S.RegisterSpace, llvm::endianness::little);
+ support::endian::write(BOS, S.ShaderVisibility, llvm::endianness::little);
+ }
}
assert(Storage.size() == getSize());
OS.write(Storage.data(), Storage.size());
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index b38ab516a3bb5..0cd3dc72505ef 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -27,6 +27,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cmath>
#include <cstdint>
#include <optional>
#include <utility>
@@ -55,6 +56,13 @@ static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
return std::nullopt;
}
+static std::optional<APFloat> extractMdFloatValue(MDNode *Node,
+ unsigned int OpId) {
+ if (auto *CI = mdconst::dyn_extract<ConstantFP>(Node->getOperand(OpId).get()))
+ return CI->getValue();
+ return std::nullopt;
+}
+
static std::optional<StringRef> extractMdStringValue(MDNode *Node,
unsigned int OpId) {
MDString *NodeText = dyn_cast<MDString>(Node->getOperand(OpId));
@@ -258,6 +266,81 @@ static bool parseDescriptorTable(LLVMContext *Ctx,
return false;
}
+static bool parseStaticSampler(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
+ MDNode *StaticSamplerNode) {
+ if (StaticSamplerNode->getNumOperands() != 14)
+ return reportError(Ctx, "Invalid format for Static Sampler");
+
+ dxbc::RTS0::v1::StaticSampler Sampler;
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 1))
+ Sampler.Filter = *Val;
+ else
+ return reportError(Ctx, "Invalid value for Filter");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 2))
+ Sampler.AddressU = *Val;
+ else
+ return reportError(Ctx, "Invalid value for AddressU");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 3))
+ Sampler.AddressV = *Val;
+ else
+ return reportError(Ctx, "Invalid value for AddressV");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 4))
+ Sampler.AddressW = *Val;
+ else
+ return reportError(Ctx, "Invalid value for AddressW");
+
+ if (std::optional<APFloat> Val = extractMdFloatValue(StaticSamplerNode, 5))
+ Sampler.MipLODBias = Val->convertToFloat();
+ else
+ return reportError(Ctx, "Invalid value for MipLODBias");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 6))
+ Sampler.MaxAnisotropy = *Val;
+ else
+ return reportError(Ctx, "Invalid value for MaxAnisotropy");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 7))
+ Sampler.ComparisonFunc = *Val;
+ else
+ return reportError(Ctx, "Invalid value for ComparisonFunc ");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 8))
+ Sampler.BorderColor = *Val;
+ else
+ return reportError(Ctx, "Invalid value for ComparisonFunc ");
+
+ if (std::optional<APFloat> Val = extractMdFloatValue(StaticSamplerNode, 9))
+ Sampler.MinLOD = Val->convertToFloat();
+ else
+ return reportError(Ctx, "Invalid value for MinLOD");
+
+ if (std::optional<APFloat> Val = extractMdFloatValue(StaticSamplerNode, 10))
+ Sampler.MaxLOD = Val->convertToFloat();
+ else
+ return reportError(Ctx, "Invalid value for MaxLOD");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 11))
+ Sampler.ShaderRegister = *Val;
+ else
+ return reportError(Ctx, "Invalid value for ShaderRegister");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 12))
+ Sampler.RegisterSpace = *Val;
+ else
+ return reportError(Ctx, "Invalid value for RegisterSpace");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 13))
+ Sampler.ShaderVisibility = *Val;
+ else
+ return reportError(Ctx, "Invalid value for ShaderVisibility");
+
+ RSD.StaticSamplers.push_back(Sampler);
+ return false;
+}
+
static bool parseRootSignatureElement(LLVMContext *Ctx,
mcdxbc::RootSignatureDesc &RSD,
MDNode *Element) {
@@ -273,6 +356,7 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
.Case("RootSRV", RootSignatureElementKind::SRV)
.Case("RootUAV", RootSignatureElementKind::UAV)
.Case("DescriptorTable", RootSignatureElementKind::DescriptorTable)
+ .Case("StaticSampler", RootSignatureElementKind::StaticSamplers)
.Default(RootSignatureElementKind::Error);
switch (ElementKind) {
@@ -287,6 +371,8 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
return parseRootDescriptors(Ctx, RSD, Element, ElementKind);
case RootSignatureElementKind::DescriptorTable:
return parseDescriptorTable(Ctx, RSD, Element);
+ case RootSignatureElementKind::StaticSamplers:
+ return parseStaticSampler(Ctx, RSD, Element);
case RootSignatureElementKind::Error:
return reportError(Ctx, "Invalid Root Signature Element: " + *ElementText);
}
@@ -347,6 +433,7 @@ static bool isFlagSet(uint32_t Flags, FlagTypes... FlagsToCheck) {
static bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
uint32_t Flags) {
+
bool IsSampler =
(Type == llvm::to_underlying(dxbc::DescriptorRangeType::Sampler));
@@ -399,6 +486,127 @@ static bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
return false;
}
+static bool verifySamplerFilter(uint32_t Filter) {
+ switch (Filter) {
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_MAG_MIP_POINT):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MIN_POINT_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_POINT_MAG_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_LINEAR_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MIN_LINEAR_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_MAG_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::ANISOTROPIC):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_POINT_MAG_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_LINEAR_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_MAG_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::COMPARISON_ANISOTROPIC):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_POINT_MAG_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_LINEAR_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_MAG_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MINIMUM_ANISOTROPIC):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_POINT_MAG_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_LINEAR_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_MAG_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MAXIMUM_ANISOTROPIC):
+ return true;
+ }
+ return false;
+}
+
+// Values allowed here:
+// https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode#syntax
+static bool verifyAddress(uint32_t Address) {
+ switch (Address) {
+ case llvm::to_underlying(dxbc::TextureAddressMode::Border):
+ case llvm::to_underlying(dxbc::TextureAddressMode::Clamp):
+ case llvm::to_underlying(dxbc::TextureAddressMode::Mirror):
+ case llvm::to_underlying(dxbc::TextureAddressMode::MirrorOnce):
+ case llvm::to_underlying(dxbc::TextureAddressMode::Wrap):
+ return true;
+ }
+
+ return false;
+}
+
+static bool verifyMipLODBias(float MipLODBias) {
+ return MipLODBias >= -16.f && MipLODBias <= 16.f;
+}
+
+static bool verifyMaxAnisotropy(uint32_t MaxAnisotropy) {
+ return MaxAnisotropy <= 16u;
+}
+
+static bool verifyComparisonFunc(uint32_t ComparisonFunc) {
+ switch (ComparisonFunc) {
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::Never):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::Less):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::Equal):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::LessEqual):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::Greater):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::NotEqual):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::GreaterEqual):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::Always):
+ return true;
+ }
+ return false;
+}
+
+static bool verifyBorderColor(uint32_t BorderColor) {
+ switch (BorderColor) {
+ case llvm::to_underlying(dxbc::SamplersBorderColor::TransparentBlack):
+ case llvm::to_underlying(dxbc::SamplersBorderColor::OpaqueBlack):
+ case llvm::to_underlying(dxbc::SamplersBorderColor::OpaqueWhite):
+ case llvm::to_underlying(dxbc::SamplersBorderColor::OpaqueBlackUint):
+ case llvm::to_underlying(dxbc::SamplersBorderColor::OpaqueWhiteUint):
+ return true;
+ }
+ return false;
+}
+
+static bool verifyLOD(float LOD) { return !std::isnan(LOD); }
+
static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
if (!verifyVersion(RSD.Version)) {
@@ -456,6 +664,48 @@ static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
}
}
+ for (const dxbc::RTS0::v1::StaticSampler &Sampler : RSD.StaticSamplers) {
+ if (!verifySamplerFilter(Sampler.Filter))
+ return reportValueError(Ctx, "Filter", Sampler.Filter);
+
+ if (!verifyAddress(Sampler.AddressU))
+ return reportValueError(Ctx, "AddressU", Sampler.AddressU);
+
+ if (!verifyAddress(Sampler.AddressV))
+ return reportValueError(Ctx, "AddressV", Sampler.AddressV);
+
+ if (!verifyAddress(Sampler.AddressW))
+ return reportValueError(Ctx, "AddressW", Sampler.AddressW);
+
+ if (!verifyMipLODBias(Sampler.MipLODBias))
+ return reportValueError(Ctx, "MipLODBias", Sampler.MipLODBias);
+
+ if (!verifyMaxAnisotropy(Sampler.MaxAnisotropy))
+ return reportValueError(Ctx, "MaxAnisotropy", Sampler.MaxAnisotropy);
+
+ if (!verifyComparisonFunc(Sampler.ComparisonFunc))
+ return reportValueError(Ctx, "ComparisonFunc", Sampler.ComparisonFunc);
+
+ if (!verifyBorderColor(Sampler.BorderColor))
+ return reportValueError(Ctx, "BorderColor", Sampler.BorderColor);
+
+ if (!verifyLOD(Sampler.MinLOD))
+ return reportValueError(Ctx, "MinLOD", Sampler.MinLOD);
+
+ if (!verifyLOD(Sampler.MaxLOD))
+ return reportValueError(Ctx, "MaxLOD", Sampler.MaxLOD);
+
+ if (!verifyRegisterValue(Sampler.ShaderRegister))
+ return reportValueError(Ctx, "ShaderRegister", Sampler.ShaderRegister);
+
+ if (!verifyRegisterSpace(Sampler.RegisterSpace))
+ return reportValueError(Ctx, "RegisterSpace", Sampler.RegisterSpace);
+
+ if (!dxbc::isValidShaderVisibility(Sampler.ShaderVisibility))
+ return reportValueError(Ctx, "ShaderVisibility",
+ Sampler.ShaderVisibility);
+ }
+
return false;
}
@@ -529,6 +779,9 @@ analyzeModule(Module &M) {
// offset will always equal to the header size.
RSD.RootParameterOffset = sizeof(dxbc::RTS0::v1::RootSignatureHeader);
+ // static sampler offset is calculated when writting dxcontainer.
+ RSD.StaticSamplersOffset = 0u;
+
if (parse(Ctx, RSD, RootElementListNode) || validate(Ctx, RSD)) {
return RSDMap;
}
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index b45cebc15fd39..be5cc78bc6bdf 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -32,6 +32,7 @@ enum class RootSignatureElementKind {
UAV = 4,
CBV = 5,
DescriptorTable = 6,
+ StaticSamplers = 7
};
class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
friend AnalysisInfoMixin<RootSignatureAnalysis>;
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressU.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressU.ll
new file mode 100644
index 0000000000000..124803e36a450
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressU.ll
@@ -0,0 +1,19 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+; CHECK: error: Invalid value for AddressU: 666
+; CHECK-NOT: Root Signature Definitions
+
+define void @main() #0 {
+entry:
+ ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"StaticSampler", i32 4, i32 666, i32 3, i32 5, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float -1.280000e+02, float 1.280000e+02, i32 42, i32 0, i32 0 }
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressV.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressV.ll
new file mode 100644
index 0000000000000..e2c5de1c36a0c
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressV.ll
@@ -0,0 +1,19 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+; CHECK: error: Invalid value for AddressV: 666
+; CHECK-NOT: Root Signature Definitions
+
+define void @main() #0 {
+entry:
+ ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"StaticSampler", i32 4, i32 2, i32 666, i32 5, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float -1.280000e+02, float 1.280000e+02, i32 42, i32 0, i32 0 }
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressW.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressW.ll
new file mode 100644
index 0000000000000..08fc8fa9e5093
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressW.ll
@@ -0,0 +1,19 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+; CHECK: error: Invalid value for AddressW: 666
+; CHECK-NOT: Root Signature Definitions
+
+define void @main() #0 {
+entry:
+ ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"StaticSampler", i32 4, i32 2, i32 3, i32 666, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float...
[truncated]
|
@llvm/pr-subscribers-mc Author: None (joaosaffran) ChangesThis patch introduces the following changes to the DirectX container implementation:
Testing:
Patch is 32.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143422.diff 17 Files Affected:
diff --git a/llvm/lib/MC/DXContainerRootSignature.cpp b/llvm/lib/MC/DXContainerRootSignature.cpp
index 6c71823a51f85..77d648a739b87 100644
--- a/llvm/lib/MC/DXContainerRootSignature.cpp
+++ b/llvm/lib/MC/DXContainerRootSignature.cpp
@@ -71,12 +71,16 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
BOS.reserveExtraSpace(getSize());
const uint32_t NumParameters = ParametersContainer.size();
-
+ const uint32_t NumSamplers = StaticSamplers.size();
support::endian::write(BOS, Version, llvm::endianness::little);
support::endian::write(BOS, NumParameters, llvm::endianness::little);
support::endian::write(BOS, RootParameterOffset, llvm::endianness::little);
- support::endian::write(BOS, NumStaticSamplers, llvm::endianness::little);
- support::endian::write(BOS, StaticSamplersOffset, llvm::endianness::little);
+ support::endian::write(BOS, NumSamplers, llvm::endianness::little);
+ uint32_t SSO = StaticSamplersOffset;
+ if (NumSamplers > 0)
+ SSO = writePlaceholder(BOS);
+ else
+ support::endian::write(BOS, SSO, llvm::endianness::little);
support::endian::write(BOS, Flags, llvm::endianness::little);
SmallVector<uint32_t> ParamsOffsets;
@@ -142,20 +146,23 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
}
}
}
- for (const auto &S : StaticSamplers) {
- support::endian::write(BOS, S.Filter, llvm::endianness::little);
- support::endian::write(BOS, S.AddressU, llvm::endianness::little);
- support::endian::write(BOS, S.AddressV, llvm::endianness::little);
- support::endian::write(BOS, S.AddressW, llvm::endianness::little);
- support::endian::write(BOS, S.MipLODBias, llvm::endianness::little);
- support::endian::write(BOS, S.MaxAnisotropy, llvm::endianness::little);
- support::endian::write(BOS, S.ComparisonFunc, llvm::endianness::little);
- support::endian::write(BOS, S.BorderColor, llvm::endianness::little);
- support::endian::write(BOS, S.MinLOD, llvm::endianness::little);
- support::endian::write(BOS, S.MaxLOD, llvm::endianness::little);
- support::endian::write(BOS, S.ShaderRegister, llvm::endianness::little);
- support::endian::write(BOS, S.RegisterSpace, llvm::endianness::little);
- support::endian::write(BOS, S.ShaderVisibility, llvm::endianness::little);
+ if (NumSamplers > 0) {
+ rewriteOffsetToCurrentByte(BOS, SSO);
+ for (const auto &S : StaticSamplers) {
+ support::endian::write(BOS, S.Filter, llvm::endianness::little);
+ support::endian::write(BOS, S.AddressU, llvm::endianness::little);
+ support::endian::write(BOS, S.AddressV, llvm::endianness::little);
+ support::endian::write(BOS, S.AddressW, llvm::endianness::little);
+ support::endian::write(BOS, S.MipLODBias, llvm::endianness::little);
+ support::endian::write(BOS, S.MaxAnisotropy, llvm::endianness::little);
+ support::endian::write(BOS, S.ComparisonFunc, llvm::endianness::little);
+ support::endian::write(BOS, S.BorderColor, llvm::endianness::little);
+ support::endian::write(BOS, S.MinLOD, llvm::endianness::little);
+ support::endian::write(BOS, S.MaxLOD, llvm::endianness::little);
+ support::endian::write(BOS, S.ShaderRegister, llvm::endianness::little);
+ support::endian::write(BOS, S.RegisterSpace, llvm::endianness::little);
+ support::endian::write(BOS, S.ShaderVisibility, llvm::endianness::little);
+ }
}
assert(Storage.size() == getSize());
OS.write(Storage.data(), Storage.size());
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index b38ab516a3bb5..0cd3dc72505ef 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -27,6 +27,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cmath>
#include <cstdint>
#include <optional>
#include <utility>
@@ -55,6 +56,13 @@ static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
return std::nullopt;
}
+static std::optional<APFloat> extractMdFloatValue(MDNode *Node,
+ unsigned int OpId) {
+ if (auto *CI = mdconst::dyn_extract<ConstantFP>(Node->getOperand(OpId).get()))
+ return CI->getValue();
+ return std::nullopt;
+}
+
static std::optional<StringRef> extractMdStringValue(MDNode *Node,
unsigned int OpId) {
MDString *NodeText = dyn_cast<MDString>(Node->getOperand(OpId));
@@ -258,6 +266,81 @@ static bool parseDescriptorTable(LLVMContext *Ctx,
return false;
}
+static bool parseStaticSampler(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
+ MDNode *StaticSamplerNode) {
+ if (StaticSamplerNode->getNumOperands() != 14)
+ return reportError(Ctx, "Invalid format for Static Sampler");
+
+ dxbc::RTS0::v1::StaticSampler Sampler;
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 1))
+ Sampler.Filter = *Val;
+ else
+ return reportError(Ctx, "Invalid value for Filter");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 2))
+ Sampler.AddressU = *Val;
+ else
+ return reportError(Ctx, "Invalid value for AddressU");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 3))
+ Sampler.AddressV = *Val;
+ else
+ return reportError(Ctx, "Invalid value for AddressV");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 4))
+ Sampler.AddressW = *Val;
+ else
+ return reportError(Ctx, "Invalid value for AddressW");
+
+ if (std::optional<APFloat> Val = extractMdFloatValue(StaticSamplerNode, 5))
+ Sampler.MipLODBias = Val->convertToFloat();
+ else
+ return reportError(Ctx, "Invalid value for MipLODBias");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 6))
+ Sampler.MaxAnisotropy = *Val;
+ else
+ return reportError(Ctx, "Invalid value for MaxAnisotropy");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 7))
+ Sampler.ComparisonFunc = *Val;
+ else
+ return reportError(Ctx, "Invalid value for ComparisonFunc ");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 8))
+ Sampler.BorderColor = *Val;
+ else
+ return reportError(Ctx, "Invalid value for ComparisonFunc ");
+
+ if (std::optional<APFloat> Val = extractMdFloatValue(StaticSamplerNode, 9))
+ Sampler.MinLOD = Val->convertToFloat();
+ else
+ return reportError(Ctx, "Invalid value for MinLOD");
+
+ if (std::optional<APFloat> Val = extractMdFloatValue(StaticSamplerNode, 10))
+ Sampler.MaxLOD = Val->convertToFloat();
+ else
+ return reportError(Ctx, "Invalid value for MaxLOD");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 11))
+ Sampler.ShaderRegister = *Val;
+ else
+ return reportError(Ctx, "Invalid value for ShaderRegister");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 12))
+ Sampler.RegisterSpace = *Val;
+ else
+ return reportError(Ctx, "Invalid value for RegisterSpace");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 13))
+ Sampler.ShaderVisibility = *Val;
+ else
+ return reportError(Ctx, "Invalid value for ShaderVisibility");
+
+ RSD.StaticSamplers.push_back(Sampler);
+ return false;
+}
+
static bool parseRootSignatureElement(LLVMContext *Ctx,
mcdxbc::RootSignatureDesc &RSD,
MDNode *Element) {
@@ -273,6 +356,7 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
.Case("RootSRV", RootSignatureElementKind::SRV)
.Case("RootUAV", RootSignatureElementKind::UAV)
.Case("DescriptorTable", RootSignatureElementKind::DescriptorTable)
+ .Case("StaticSampler", RootSignatureElementKind::StaticSamplers)
.Default(RootSignatureElementKind::Error);
switch (ElementKind) {
@@ -287,6 +371,8 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
return parseRootDescriptors(Ctx, RSD, Element, ElementKind);
case RootSignatureElementKind::DescriptorTable:
return parseDescriptorTable(Ctx, RSD, Element);
+ case RootSignatureElementKind::StaticSamplers:
+ return parseStaticSampler(Ctx, RSD, Element);
case RootSignatureElementKind::Error:
return reportError(Ctx, "Invalid Root Signature Element: " + *ElementText);
}
@@ -347,6 +433,7 @@ static bool isFlagSet(uint32_t Flags, FlagTypes... FlagsToCheck) {
static bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
uint32_t Flags) {
+
bool IsSampler =
(Type == llvm::to_underlying(dxbc::DescriptorRangeType::Sampler));
@@ -399,6 +486,127 @@ static bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
return false;
}
+static bool verifySamplerFilter(uint32_t Filter) {
+ switch (Filter) {
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_MAG_MIP_POINT):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MIN_POINT_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_POINT_MAG_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_LINEAR_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MIN_LINEAR_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_MAG_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::ANISOTROPIC):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_POINT_MAG_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_LINEAR_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::COMPARISON_MIN_MAG_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::COMPARISON_ANISOTROPIC):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_POINT_MAG_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_LINEAR_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MINIMUM_MIN_MAG_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MINIMUM_ANISOTROPIC):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_POINT_MAG_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_LINEAR_MAG_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_MAG_LINEAR_MIP_POINT):
+ case llvm::to_underlying(
+ dxbc::StaticSamplerFilter::MAXIMUM_MIN_MAG_MIP_LINEAR):
+ case llvm::to_underlying(dxbc::StaticSamplerFilter::MAXIMUM_ANISOTROPIC):
+ return true;
+ }
+ return false;
+}
+
+// Values allowed here:
+// https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode#syntax
+static bool verifyAddress(uint32_t Address) {
+ switch (Address) {
+ case llvm::to_underlying(dxbc::TextureAddressMode::Border):
+ case llvm::to_underlying(dxbc::TextureAddressMode::Clamp):
+ case llvm::to_underlying(dxbc::TextureAddressMode::Mirror):
+ case llvm::to_underlying(dxbc::TextureAddressMode::MirrorOnce):
+ case llvm::to_underlying(dxbc::TextureAddressMode::Wrap):
+ return true;
+ }
+
+ return false;
+}
+
+static bool verifyMipLODBias(float MipLODBias) {
+ return MipLODBias >= -16.f && MipLODBias <= 16.f;
+}
+
+static bool verifyMaxAnisotropy(uint32_t MaxAnisotropy) {
+ return MaxAnisotropy <= 16u;
+}
+
+static bool verifyComparisonFunc(uint32_t ComparisonFunc) {
+ switch (ComparisonFunc) {
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::Never):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::Less):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::Equal):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::LessEqual):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::Greater):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::NotEqual):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::GreaterEqual):
+ case llvm::to_underlying(dxbc::SamplersComparisonFunction::Always):
+ return true;
+ }
+ return false;
+}
+
+static bool verifyBorderColor(uint32_t BorderColor) {
+ switch (BorderColor) {
+ case llvm::to_underlying(dxbc::SamplersBorderColor::TransparentBlack):
+ case llvm::to_underlying(dxbc::SamplersBorderColor::OpaqueBlack):
+ case llvm::to_underlying(dxbc::SamplersBorderColor::OpaqueWhite):
+ case llvm::to_underlying(dxbc::SamplersBorderColor::OpaqueBlackUint):
+ case llvm::to_underlying(dxbc::SamplersBorderColor::OpaqueWhiteUint):
+ return true;
+ }
+ return false;
+}
+
+static bool verifyLOD(float LOD) { return !std::isnan(LOD); }
+
static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
if (!verifyVersion(RSD.Version)) {
@@ -456,6 +664,48 @@ static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
}
}
+ for (const dxbc::RTS0::v1::StaticSampler &Sampler : RSD.StaticSamplers) {
+ if (!verifySamplerFilter(Sampler.Filter))
+ return reportValueError(Ctx, "Filter", Sampler.Filter);
+
+ if (!verifyAddress(Sampler.AddressU))
+ return reportValueError(Ctx, "AddressU", Sampler.AddressU);
+
+ if (!verifyAddress(Sampler.AddressV))
+ return reportValueError(Ctx, "AddressV", Sampler.AddressV);
+
+ if (!verifyAddress(Sampler.AddressW))
+ return reportValueError(Ctx, "AddressW", Sampler.AddressW);
+
+ if (!verifyMipLODBias(Sampler.MipLODBias))
+ return reportValueError(Ctx, "MipLODBias", Sampler.MipLODBias);
+
+ if (!verifyMaxAnisotropy(Sampler.MaxAnisotropy))
+ return reportValueError(Ctx, "MaxAnisotropy", Sampler.MaxAnisotropy);
+
+ if (!verifyComparisonFunc(Sampler.ComparisonFunc))
+ return reportValueError(Ctx, "ComparisonFunc", Sampler.ComparisonFunc);
+
+ if (!verifyBorderColor(Sampler.BorderColor))
+ return reportValueError(Ctx, "BorderColor", Sampler.BorderColor);
+
+ if (!verifyLOD(Sampler.MinLOD))
+ return reportValueError(Ctx, "MinLOD", Sampler.MinLOD);
+
+ if (!verifyLOD(Sampler.MaxLOD))
+ return reportValueError(Ctx, "MaxLOD", Sampler.MaxLOD);
+
+ if (!verifyRegisterValue(Sampler.ShaderRegister))
+ return reportValueError(Ctx, "ShaderRegister", Sampler.ShaderRegister);
+
+ if (!verifyRegisterSpace(Sampler.RegisterSpace))
+ return reportValueError(Ctx, "RegisterSpace", Sampler.RegisterSpace);
+
+ if (!dxbc::isValidShaderVisibility(Sampler.ShaderVisibility))
+ return reportValueError(Ctx, "ShaderVisibility",
+ Sampler.ShaderVisibility);
+ }
+
return false;
}
@@ -529,6 +779,9 @@ analyzeModule(Module &M) {
// offset will always equal to the header size.
RSD.RootParameterOffset = sizeof(dxbc::RTS0::v1::RootSignatureHeader);
+ // static sampler offset is calculated when writting dxcontainer.
+ RSD.StaticSamplersOffset = 0u;
+
if (parse(Ctx, RSD, RootElementListNode) || validate(Ctx, RSD)) {
return RSDMap;
}
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index b45cebc15fd39..be5cc78bc6bdf 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -32,6 +32,7 @@ enum class RootSignatureElementKind {
UAV = 4,
CBV = 5,
DescriptorTable = 6,
+ StaticSamplers = 7
};
class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
friend AnalysisInfoMixin<RootSignatureAnalysis>;
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressU.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressU.ll
new file mode 100644
index 0000000000000..124803e36a450
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressU.ll
@@ -0,0 +1,19 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+; CHECK: error: Invalid value for AddressU: 666
+; CHECK-NOT: Root Signature Definitions
+
+define void @main() #0 {
+entry:
+ ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"StaticSampler", i32 4, i32 666, i32 3, i32 5, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float -1.280000e+02, float 1.280000e+02, i32 42, i32 0, i32 0 }
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressV.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressV.ll
new file mode 100644
index 0000000000000..e2c5de1c36a0c
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressV.ll
@@ -0,0 +1,19 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+; CHECK: error: Invalid value for AddressV: 666
+; CHECK-NOT: Root Signature Definitions
+
+define void @main() #0 {
+entry:
+ ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"StaticSampler", i32 4, i32 2, i32 666, i32 5, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float -1.280000e+02, float 1.280000e+02, i32 42, i32 0, i32 0 }
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressW.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressW.ll
new file mode 100644
index 0000000000000..08fc8fa9e5093
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-AddressW.ll
@@ -0,0 +1,19 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+; CHECK: error: Invalid value for AddressW: 666
+; CHECK-NOT: Root Signature Definitions
+
+define void @main() #0 {
+entry:
+ ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"StaticSampler", i32 4, i32 2, i32 3, i32 666, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float...
[truncated]
|
@@ -399,6 +486,127 @@ static bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, | |||
return false; | |||
} | |||
|
|||
static bool verifySamplerFilter(uint32_t Filter) { | |||
switch (Filter) { | |||
case llvm::to_underlying(dxbc::StaticSamplerFilter::MIN_MAG_MIP_POINT): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might be able to use a similar BitEnumMask
technique here?
Or just a <=
comparison?
if (!verifySamplerFilter(Sampler.Filter)) | ||
return reportValueError(Ctx, "Filter", Sampler.Filter); | ||
|
||
if (!verifyAddress(Sampler.AddressU)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thought that just came up. I don't think it is required for us to early exit on all these verifications.
Maybe we can report all invalid errors in one go rather than exiting on the first one? Can you provide an argument for why or why not?
I would assume reporting all errors (so long as they aren't too verbose) reduces the number of compile cycles for the user to correct their input.
0b4111a
to
24f38bd
Compare
Implements static samplers parsing from root signature metadata representation. This is required to support Root Signatures in HLSL.
Closes: #126641