Skip to content

[DXC] Add -metal flag to DXC driver #130173

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

Merged
merged 1 commit into from
Mar 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion clang/include/clang/Driver/Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ class Action {
LinkerWrapperJobClass,
StaticLibJobClass,
BinaryAnalyzeJobClass,
BinaryTranslatorJobClass,

JobClassFirst = PreprocessJobClass,
JobClassLast = BinaryAnalyzeJobClass
JobClassLast = BinaryTranslatorJobClass
};

// The offloading kind determines if this action is binded to a particular
Expand Down Expand Up @@ -675,6 +676,17 @@ class BinaryAnalyzeJobAction : public JobAction {
}
};

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

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -9085,6 +9085,7 @@ def : Option<["/", "-"], "Qembed_debug", KIND_FLAG>, Group<dxc_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<dxc_Group>,
HelpText<"Specify the target environment">,
Values<"vulkan1.2, vulkan1.3">;
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Driver/Action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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) {}
10 changes: 10 additions & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4672,6 +4672,16 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
Actions.push_back(C.MakeAction<BinaryAnalyzeJobAction>(
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<BinaryTranslatorJobAction>(
LastAction, types::TY_DX_CONTAINER));
}
}

// Claim ignored clang-cl options.
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/Driver/ToolChains/HLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Command>(JA, *this, ResponseFileSupport::None(),
Exec, CmdArgs, Inputs, Input));
}

/// DirectX Toolchain
HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
Expand All @@ -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);
}
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/Driver/ToolChains/HLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ class LLVM_LIBRARY_VISIBILITY Validator : public Tool {
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

Expand Down Expand Up @@ -57,6 +70,7 @@ class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain {

private:
mutable std::unique_ptr<tools::hlsl::Validator> Validator;
mutable std::unique_ptr<tools::hlsl::MetalConverter> MetalConverter;
};

} // end namespace toolchains
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Driver/HLSL/metal-converter.hlsl
Original file line number Diff line number Diff line change
@@ -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<float4> In : register(u0, space0);
RWBuffer<float4> Out : register(u1, space4);

[numthreads(1,1,1)]
void main(uint GI : SV_GroupIndex) {
Out[GI] = In[GI] * In[GI];
}