Skip to content

Commit f7f1e3d

Browse files
authored
[Metal] Add experimental Metal support (#6805)
This adds a new `-metal` flag to DXC which can be used to generate Metal's IR directly from DXC after compilation. There are some limitations in this flag which are worth noting: 1) It does not support library shaders (yet) 2) It does not support disassembly (yet) 3) It is _wildly_ under tested because wtihout (2) we can't do anything to really verify correct output (yay?)
1 parent 0a11435 commit f7f1e3d

13 files changed

Lines changed: 177 additions & 1 deletion

File tree

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ Development kits containing only the dxc.exe driver app, the dxcompiler.dll, and
3434

3535
As an example of community contribution, this project can also target the [SPIR-V](https://www.khronos.org/registry/spir-v/) intermediate representation. Please see the [doc](docs/SPIR-V.rst) for how HLSL features are mapped to SPIR-V, and the [wiki](https://github.com/microsoft/DirectXShaderCompiler/wiki/SPIR%E2%80%90V-CodeGen) page for how to build, use, and contribute to the SPIR-V CodeGen.
3636

37+
### Metal CodeGen
38+
39+
When built from source DXC can utilize the [Metal Shader
40+
Converter](https://developer.apple.com/metal/shader-converter/) if it is
41+
available during build and configuration time. This allows DXC to generate Metal
42+
shader libraries directly using the `-metal` flag.
43+
44+
Note: DXC cannot currently disassemble Metal shaders so the `-Fc` flag cannot be
45+
used in conjunction with the `-Fo` flag.
46+
3747
## Building Sources
3848

3949
See the full documentation for [Building and testing DXC](docs/BuildingAndTestingDXC.rst) for detailed instructions.

cmake/config-ix.cmake

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,3 +568,12 @@ else()
568568
endif()
569569

570570
string(REPLACE " " ";" LLVM_BINDINGS_LIST "${LLVM_BINDINGS}")
571+
572+
# HLSL Change Begin - Metal IR Converter
573+
find_package(MetalIRConverter)
574+
if (METAL_IRCONVERTER_FOUND)
575+
set(ENABLE_METAL_CODEGEN On)
576+
message(STATUS "Enabling Metal Support")
577+
add_definitions(-DENABLE_METAL_CODEGEN)
578+
endif()
579+
# HLSL Change End - Metal IR Converter
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
find_path(METAL_IRCONVERTER_INCLUDE_DIR metal_irconverter.h
2+
HINTS /usr/local/include/metal_irconverter
3+
DOC "Path to metal IR converter headers"
4+
)
5+
6+
find_library(METAL_IRCONVERTER_LIB NAMES metalirconverter
7+
PATH_SUFFIXES lib
8+
)
9+
10+
include(FindPackageHandleStandardArgs)
11+
FIND_PACKAGE_HANDLE_STANDARD_ARGS(METAL_IRCONVERTER
12+
REQUIRED_VARS METAL_IRCONVERTER_LIB METAL_IRCONVERTER_INCLUDE_DIR)
13+
14+
message(STATUS "Metal IR Converter Include Dir: ${METAL_IRCONVERTER_INCLUDE_DIR}")
15+
message(STATUS "Metal IR Converter Library: ${METAL_IRCONVERTER_LIB}")
16+
mark_as_advanced(METAL_IRCONVERTER_LIB METAL_IRCONVERTER_INCLUDE_DIR)

include/dxc/Support/HLSLOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ class DxcOpts {
274274
SpirvOptions; // All SPIR-V CodeGen-related options
275275
#endif
276276
// SPIRV Change Ends
277+
278+
bool GenMetal = false; // OPT_metal
277279
};
278280

279281
/// Use this class to capture, convert and handle the lifetime for the

include/dxc/Support/HLSLOptions.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,11 @@ def disable_exception_handling : Flag<["-", "/"], "disable-exception-handling">,
346346
def skip_serialization : Flag<["-", "/"], "skip-serialization">, Group<hlslcore_Group>, Flags<[CoreOption, HelpHidden]>,
347347
HelpText<"Return a module interface instead of serialized output">;
348348

349+
def metal : Flag<["-"], "metal">,
350+
Group<spirv_Group>,
351+
Flags<[CoreOption, DriverOption]>,
352+
HelpText<"Generate Metal code">;
353+
349354
// SPIRV Change Starts
350355
def spirv : Flag<["-"], "spirv">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
351356
HelpText<"Generate SPIR-V code">;

lib/DxcSupport/HLSLOptions.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
10891089

10901090
addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, opts.Warnings);
10911091

1092+
opts.GenMetal = Args.hasFlag(OPT_metal, OPT_INVALID, false);
1093+
10921094
// SPIRV Change Starts
10931095
#ifdef ENABLE_SPIRV_CODEGEN
10941096
opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false);
@@ -1313,6 +1315,21 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
13131315
#endif // ENABLE_SPIRV_CODEGEN
13141316
// SPIRV Change Ends
13151317

1318+
#ifndef ENABLE_METAL_CODEGEN
1319+
if (opts.GenMetal) {
1320+
errors << "Metal CodeGen not available. "
1321+
"Please rebuild with Metal IR Converter installed.";
1322+
return 1;
1323+
}
1324+
#endif
1325+
1326+
if (opts.GenMetal) {
1327+
if (!opts.AssemblyCode.empty() || opts.OutputObject.empty()) {
1328+
errors << "Disassembly of Metal IR not supported (yet).";
1329+
return 1;
1330+
}
1331+
}
1332+
13161333
// Validation for DebugInfo here because spirv uses same DebugInfo opt,
13171334
// and legacy wrappers will add EmbedDebug in this case, leading to this
13181335
// failing if placed before spirv path sets DebugInfo to true.

tools/clang/test/DXC/metal.test

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// REQUIRES: metal
2+
3+
// Metal libraries are LLVM bitcode. This check inspects the magic number from
4+
// the metal library output.
5+
// RUN: %dxc %S/Inputs/smoke.hlsl /T ps_6_0 -metal -Fo Tmp.metal
6+
// RUN: head -c 4 Tmp.metal | FileCheck -check-prefix=MTL %s
7+
// MTL: {{^MTLB}}

tools/clang/test/DXC/no_metal.test

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// UNSUPPORTED: metal
2+
3+
// RUN:not %dxc %S/Inputs/smoke.hlsl /T ps_6_0 -metal 2>&1 | FileCheck %s
4+
// CHECK:Metal CodeGen not available
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// REQUIRES: metal
2+
3+
// These cases both fail because the shader converter library cannot emit
4+
// textual IR.
5+
// RUN: not %dxc %S/Inputs/smoke.hlsl /T ps_6_0 -metal -Fo Tmp.metal -Fc Tmp.air 2>&1 | FileCheck %s
6+
// RUN: not %dxc %S/Inputs/smoke.hlsl /T ps_6_0 -metal 2>&1 | FileCheck %s
7+
// CHECK: Disassembly of Metal IR not supported (yet).

tools/clang/test/lit.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,9 @@ if config.enable_backtrace == "1":
504504
if config.spirv:
505505
config.available_features.add("spirv")
506506

507+
if config.metal:
508+
config.available_features.add("metal")
509+
507510
# Check supported dxil version
508511
def get_dxil_version():
509512
result = subprocess.run([lit.util.which('dxc', llvm_tools_dir), "--version"], stdout=subprocess.PIPE)

0 commit comments

Comments
 (0)