-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
[DirectX backend] emits metadata for DXIL version. #88350
Conversation
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-backend-directx Author: Xiang Li (python3kgae) ChangesEmit named metadata "dx.version" for DXIL version. Default to DXIL 1.0 Full diff: https://github.com/llvm/llvm-project/pull/88350.diff 5 Files Affected:
diff --git a/llvm/lib/Target/DirectX/DXILMetadata.cpp b/llvm/lib/Target/DirectX/DXILMetadata.cpp
index 2d94490a7f24c3..61882f85095664 100644
--- a/llvm/lib/Target/DirectX/DXILMetadata.cpp
+++ b/llvm/lib/Target/DirectX/DXILMetadata.cpp
@@ -81,6 +81,18 @@ void dxil::createShaderModelMD(Module &M) {
Entry->addOperand(MDNode::get(Ctx, Vals));
}
+void dxil::createDXILVersionMD(Module &M) {
+ Triple TT(M.getTargetTriple());
+ VersionTuple Ver = TT.getOSVersion();
+ LLVMContext &Ctx = M.getContext();
+ IRBuilder<> B(Ctx);
+ NamedMDNode *Entry = M.getOrInsertNamedMetadata("dx.version");
+ Metadata *Vals[2];
+ Vals[0] = ConstantAsMetadata::get(B.getInt32(1));
+ Vals[1] = ConstantAsMetadata::get(B.getInt32(Ver.getMinor().value_or(0)));
+ Entry->addOperand(MDNode::get(Ctx, Vals));
+}
+
static uint32_t getShaderStage(Triple::EnvironmentType Env) {
return (uint32_t)Env - (uint32_t)llvm::Triple::Pixel;
}
diff --git a/llvm/lib/Target/DirectX/DXILMetadata.h b/llvm/lib/Target/DirectX/DXILMetadata.h
index 2f5d7d9fe7683d..c105c15f3d47af 100644
--- a/llvm/lib/Target/DirectX/DXILMetadata.h
+++ b/llvm/lib/Target/DirectX/DXILMetadata.h
@@ -33,6 +33,7 @@ class ValidatorVersionMD {
};
void createShaderModelMD(Module &M);
+void createDXILVersionMD(Module &M);
void createEntryMD(Module &M, const uint64_t ShaderFlags);
} // namespace dxil
diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
index 80d94bf0c9d488..ae6d6f96904c86 100644
--- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
+++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
@@ -48,6 +48,7 @@ bool DXILTranslateMetadata::runOnModule(Module &M) {
if (ValVerMD.isEmpty())
ValVerMD.update(VersionTuple(1, 0));
dxil::createShaderModelMD(M);
+ dxil::createDXILVersionMD(M);
const dxil::Resources &Res =
getAnalysis<DXILResourceWrapper>().getDXILResource();
diff --git a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll
new file mode 100644
index 00000000000000..254479e5f94cbd
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll
@@ -0,0 +1,12 @@
+; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s
+target triple = "dxil-pc-shadermodel6.0-vertex"
+
+; CHECK: !dx.version = !{![[DXVER:[0-9]+]]}
+; CHECK: ![[DXVER]] = !{i32 1, i32 0}
+
+define void @entry() #0 {
+entry:
+ ret void
+}
+
+attributes #0 = { noinline nounwind "hlsl.shader"="vertex" }
diff --git a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll
new file mode 100644
index 00000000000000..efeb5a1b24862e
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll
@@ -0,0 +1,12 @@
+; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s
+target triple = "dxil-pc-shadermodel6.8-compute"
+
+; CHECK: !dx.version = !{![[DXVER:[0-9]+]]}
+; CHECK: ![[DXVER]] = !{i32 1, i32 8}
+
+define void @entry() #0 {
+entry:
+ ret void
+}
+
+attributes #0 = { noinline nounwind "hlsl.numthreads"="1,2,1" "hlsl.shader"="compute" }
|
@@ -81,6 +81,18 @@ void dxil::createShaderModelMD(Module &M) { | |||
Entry->addOperand(MDNode::get(Ctx, Vals)); | |||
} | |||
|
|||
void dxil::createDXILVersionMD(Module &M) { | |||
Triple TT(M.getTargetTriple()); | |||
VersionTuple Ver = TT.getOSVersion(); |
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.
I think we should reconsider how we're representing the DXIL version. In DXC we've always made the DXIL version and Shader Model version lockstep and we've made a lot of assumptions about that.
I suggested in a separate chat channel that we should consider adding DXIL versions as sub-architectures.
I'm curious for feedback from @bharadwajy and @bogner.
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.
What are the anticipated benefits of separating the Shader Model version number and DXIL version number, given future plans for the evolution of HLSL and DXIL?
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.
Apologies for any confusion caused by me posting the comment from an alternate account (@thegreatbeanz) is me.
I can't share anything about future plans for HLSL or DXIL, aside from what is already public. That said, I don't think we need to consider future plans to see the potential benefit of keeping DXIL and SM versions separate and clearly defined.
We haven't done a great job delineating shader model versions from DXIL versions in DXC, but they are different. A good example is the quadVote DXIL Op (described here). While the quadVote DXIL Op was added in DXIL 1.7, the QuadAny/QuadAll HLSL intrinsics were retroactively added back to Shader Model 6.0 because they can be lowered to different DXIL operations on older DXIL versions. We've also done this for other new functions like the IsHelperLane
intrinsic added in Shader Model 6.6.
This means there isn't a 1:1 mapping between source-level intrinsics where shader model is our versioning, and DXIL operations where the DXIL version is our mechanism.
When we think about expanding DXIL targeting support to other languages, it is probably more clear to separate the Shader Model version (which is an HLSL concept) from the DXIL version (which is a code-generation concept).
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.
This means there isn't a 1:1 mapping between source-level intrinsics where shader model is our versioning, and DXIL operations where the DXIL version is our mechanism.
When we think about expanding DXIL targeting support to other languages, it is probably more clear to separate the Shader Model version (which is an HLSL concept) from the DXIL version (which is a code-generation concept).
This sounds wrong. Shader Model is specifically a target constraint concept applying to the features used in the IR we pass to drivers. DXIL version is an IR versioning concept. In the past, if something in HLSL could be mapped to the constraints in a shader model by the compiler, then it was legal to use in that shader model. It was never considered an HLSL concept/constraint. We may want to put constraints on HLSL APIs in the future based on the shader model used, but that is not the core role of the shader model.
We also add things to the language/API in shader model time frames, but that doesn't mean that using those things at the source level always requires compilation to those shader models. They just require a new enough compiler that has the source-level construct (like QuaAny
/QuadAll
/IsHelperLane
).
In the past, they have advanced in lock-step because with each new shader model, we have needed updates to DXIL, making it necessary to advance that version, and we can't use a newer DXIL version for an older shader model, since drivers reporting support for a particular shader model are not expected to support any newer DXIL versions beyond that shader model.
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.
Issue #91388 is created to track validation of dxil version and shader model.
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.
If the fact that this is missing is blocking something then it's probably fine to do it like this for now, but as implied by #66015 and #66016 we'll presumably need to revisit this as we evolve our story around DXIL metadata abstractions.
In any case, it's probably worth considering @thegreatbeanz's point about separating the abstraction of DXIL version from the shader model. It'll be much easier to decouple these if we design that early rather than if we bake in assumptions like this in the short term.
Can you clarify what the intent of this PR is please? It looks like it is actually trying to match current DXC behavior that assumes that the DXIL version is tied to the SM version? |
The intent for this PR is to match current DXC behavior when DXIL version is not set separately. |
Emit named metadata "dx.version". Default to DXIL 1.0
✅ With the latest revision this PR passed the C/C++ code formatter. |
llvm/lib/Transforms/Utils/DXIL.cpp
Outdated
} | ||
|
||
Expected<DXILVersion> DXILVersion::get(Module &M) { | ||
Triple TT(Triple::normalize(M.getTargetTriple())); |
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.
Normalizing the triple should be sufficient for identifying the sub architecture. @bharadwajy's PR (#90809) needed to be reverted, but when it re-lands this should radically simplify.
I think we should probably just do the simpler Longer term I'd like to go the route of #63835, where we introduce a metadata analysis pass that generates some kind of |
@@ -429,6 +429,10 @@ class Triple { | |||
/// (SubArch). This should only be called with Vulkan SPIR-V triples. | |||
VersionTuple getVulkanVersion() const; | |||
|
|||
/// Parse the DXIL version number from the OSVersion and DXIL version | |||
/// (SubArch). This should only be called with DXIL triples. | |||
VersionTuple getDXILVersion() const; |
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.
This comment doesn't seem accurate, given that getDXILVersion
doesn't currently use the OS version
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.
Updated.
llvm/lib/TargetParser/Triple.cpp
Outdated
switch (getSubArch()) { | ||
case Triple::NoSubArch: | ||
case Triple::DXILSubArch_v1_0: | ||
DXILVersion = VersionTuple(1, 0); |
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.
Can this be simplified using ParseVersionFromName?
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.
Updated.
@@ -33,6 +33,7 @@ class ValidatorVersionMD { | |||
}; | |||
|
|||
void createShaderModelMD(Module &M); | |||
void createDXILVersionMD(Module &M); |
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.
Consider expanding MD as Metadata in the function name createDXILVersionMD
as createDXILVersionMetadata
. Similarly, createShaderModelMetadata
.
Emit named metadata "dx.version" for DXIL version.
Default to DXIL 1.0
Fixes #88774