From 0ea52234fc3510463df2d8718404cede874e9b5e Mon Sep 17 00:00:00 2001 From: Chris B Date: Fri, 7 Mar 2025 17:28:41 -0600 Subject: [PATCH] [DXC] Add `-metal` flag to DXC driver (#130173) This adds a flag to the DXC driver to enable calling the metal shader converter if it is available to convert the final shader output for metal. --- clang/include/clang/Driver/Action.h | 14 +++++++++++++- clang/include/clang/Driver/Options.td | 1 + clang/lib/Driver/Action.cpp | 8 ++++++++ clang/lib/Driver/Driver.cpp | 10 ++++++++++ clang/lib/Driver/ToolChain.cpp | 1 + clang/lib/Driver/ToolChains/HLSL.cpp | 20 ++++++++++++++++++++ clang/lib/Driver/ToolChains/HLSL.h | 14 ++++++++++++++ clang/test/Driver/HLSL/metal-converter.hlsl | 14 ++++++++++++++ 8 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 clang/test/Driver/HLSL/metal-converter.hlsl diff --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h index e5307b0fcedd..92bb19314e3d 100644 --- a/clang/include/clang/Driver/Action.h +++ b/clang/include/clang/Driver/Action.h @@ -75,9 +75,10 @@ public: LinkerWrapperJobClass, StaticLibJobClass, BinaryAnalyzeJobClass, + BinaryTranslatorJobClass, JobClassFirst = PreprocessJobClass, - JobClassLast = BinaryAnalyzeJobClass + JobClassLast = BinaryTranslatorJobClass }; // The offloading kind determines if this action is binded to a particular @@ -675,6 +676,17 @@ public: } }; +class BinaryTranslatorJobAction : public JobAction { + void anchor() override; + +public: + BinaryTranslatorJobAction(Action *Input, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == BinaryTranslatorJobClass; + } +}; + } // namespace driver } // namespace clang diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index d0414aba3520..6ed579cb88d9 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -9085,6 +9085,7 @@ def : Option<["/", "-"], "Qembed_debug", KIND_FLAG>, Group, HelpText<"Embed PDB in shader container (ignored)">; def spirv : DXCFlag<"spirv">, HelpText<"Generate SPIR-V code">; +def metal : DXCFlag<"metal">, HelpText<"Generate Metal library">; def fspv_target_env_EQ : Joined<["-"], "fspv-target-env=">, Group, HelpText<"Specify the target environment">, Values<"vulkan1.2, vulkan1.3">; diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp index 0899b8ef0015..ec0972604481 100644 --- a/clang/lib/Driver/Action.cpp +++ b/clang/lib/Driver/Action.cpp @@ -50,6 +50,8 @@ const char *Action::getClassName(ActionClass AC) { return "static-lib-linker"; case BinaryAnalyzeJobClass: return "binary-analyzer"; + case BinaryTranslatorJobClass: + return "binary-translator"; } llvm_unreachable("invalid class"); @@ -459,3 +461,9 @@ void BinaryAnalyzeJobAction::anchor() {} BinaryAnalyzeJobAction::BinaryAnalyzeJobAction(Action *Input, types::ID Type) : JobAction(BinaryAnalyzeJobClass, Input, Type) {} + +void BinaryTranslatorJobAction::anchor() {} + +BinaryTranslatorJobAction::BinaryTranslatorJobAction(Action *Input, + types::ID Type) + : JobAction(BinaryTranslatorJobClass, Input, Type) {} diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index e998c94aeacd..08ae8173db6d 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -4669,6 +4669,16 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, Actions.push_back(C.MakeAction( LastAction, types::TY_DX_CONTAINER)); } + if (Args.getLastArg(options::OPT_metal)) { + Action *LastAction = Actions.back(); + // Metal shader converter runs on DXIL containers, which can either be + // validated (in which case they are TY_DX_CONTAINER), or unvalidated + // (TY_OBJECT). + if (LastAction->getType() == types::TY_DX_CONTAINER || + LastAction->getType() == types::TY_Object) + Actions.push_back(C.MakeAction( + LastAction, types::TY_DX_CONTAINER)); + } } // Claim ignored clang-cl options. diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 65acbe8a9dbe..fa810457a06c 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -639,6 +639,7 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { case Action::DsymutilJobClass: case Action::VerifyDebugInfoJobClass: case Action::BinaryAnalyzeJobClass: + case Action::BinaryTranslatorJobClass: llvm_unreachable("Invalid tool kind."); case Action::CompileJobClass: diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index ad44c2cfcd81..62e4d14390b9 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -198,6 +198,22 @@ void tools::hlsl::Validator::ConstructJob(Compilation &C, const JobAction &JA, Exec, CmdArgs, Inputs, Input)); } +void tools::hlsl::MetalConverter::ConstructJob( + Compilation &C, const JobAction &JA, const InputInfo &Output, + const InputInfoList &Inputs, const ArgList &Args, + const char *LinkingOutput) const { + std::string MSCPath = getToolChain().GetProgramPath("metal-shaderconverter"); + ArgStringList CmdArgs; + const InputInfo &Input = Inputs[0]; + CmdArgs.push_back(Input.getFilename()); + CmdArgs.push_back("-o"); + CmdArgs.push_back(Input.getFilename()); + + const char *Exec = Args.MakeArgString(MSCPath); + C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), + Exec, CmdArgs, Inputs, Input)); +} + /// DirectX Toolchain HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) @@ -214,6 +230,10 @@ Tool *clang::driver::toolchains::HLSLToolChain::getTool( if (!Validator) Validator.reset(new tools::hlsl::Validator(*this)); return Validator.get(); + case Action::BinaryTranslatorJobClass: + if (!MetalConverter) + MetalConverter.reset(new tools::hlsl::MetalConverter(*this)); + return MetalConverter.get(); default: return ToolChain::getTool(AC); } diff --git a/clang/lib/Driver/ToolChains/HLSL.h b/clang/lib/Driver/ToolChains/HLSL.h index b2a31aabab7d..86dd65f0b80c 100644 --- a/clang/lib/Driver/ToolChains/HLSL.h +++ b/clang/lib/Driver/ToolChains/HLSL.h @@ -29,6 +29,19 @@ public: const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; + +class LLVM_LIBRARY_VISIBILITY MetalConverter : public Tool { +public: + MetalConverter(const ToolChain &TC) + : Tool("hlsl::MetalConverter", "metal-shaderconverter", TC) {} + + bool hasIntegratedCPP() const override { return false; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; } // namespace hlsl } // namespace tools @@ -57,6 +70,7 @@ public: private: mutable std::unique_ptr Validator; + mutable std::unique_ptr MetalConverter; }; } // end namespace toolchains diff --git a/clang/test/Driver/HLSL/metal-converter.hlsl b/clang/test/Driver/HLSL/metal-converter.hlsl new file mode 100644 index 000000000000..4402e5044dc7 --- /dev/null +++ b/clang/test/Driver/HLSL/metal-converter.hlsl @@ -0,0 +1,14 @@ +// RUN: %clang_dxc -T cs_6_0 %s -metal -Fo tmp.mtl -### 2>&1 | FileCheck %s +// RUN: %clang_dxc -T cs_6_0 %s -metal -Vd -Fo tmp.mtl -### 2>&1 | FileCheck %s +// CHECK: "{{.*}}metal-shaderconverter{{(.exe)?}}" "tmp.mtl" "-o" "tmp.mtl" + +// RUN: %clang_dxc -T cs_6_0 %s -metal -### 2>&1 | FileCheck --check-prefix=NO_MTL %s +// NO_MTL-NOT: metal-shaderconverter + +RWBuffer In : register(u0, space0); +RWBuffer Out : register(u1, space4); + +[numthreads(1,1,1)] +void main(uint GI : SV_GroupIndex) { + Out[GI] = In[GI] * In[GI]; +}