Skip to content

Commit 5e77265

Browse files
authored
chore: keep shader compilation private + use inline shaders for Metal built-ins (#85)
* move shader compilation to examples only * Don’t use precompiled shaders for Metal * Fix compilation
1 parent 89a5037 commit 5e77265

File tree

12 files changed

+348
-607
lines changed

12 files changed

+348
-607
lines changed

CMakeLists.txt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,6 @@ if(APPLE)
109109
target_include_directories(plume PRIVATE
110110
${CMAKE_CURRENT_SOURCE_DIR}/contrib/metal-cpp
111111
)
112-
113-
# Compile and embed internal Metal shaders
114-
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/PlumeShaders.cmake)
115-
plume_build_file_to_c()
116-
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/shaders")
117-
118-
_plume_compile_metal_impl(plume "${CMAKE_CURRENT_SOURCE_DIR}/shaders/plume_clear.metal" plume_clear)
119-
_plume_compile_metal_impl(plume "${CMAKE_CURRENT_SOURCE_DIR}/shaders/plume_resolve.metal" plume_resolve)
120112
endif()
121113

122114
# Add examples if requested

cmake/PlumeShaders.cmake

Lines changed: 0 additions & 491 deletions
This file was deleted.

examples/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ set(PLUME_SDL_VULKAN_ENABLED ON CACHE BOOL "Enable SDL Vulkan integration" FORCE
77
find_package(SDL2 REQUIRED)
88

99
# Initialize shader compilation
10-
include(${CMAKE_SOURCE_DIR}/cmake/PlumeShaders.cmake)
10+
include(${CMAKE_SOURCE_DIR}/examples/cmake/PlumeShaders.cmake)
1111
plume_shaders_init()
1212

1313
# Add example subdirectories

examples/cmake/PlumeShaders.cmake

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
# PlumeShaders.cmake
2+
# Shader compilation helpers for Plume examples
3+
#
4+
# Usage (examples):
5+
# include(path/to/plume/examples/cmake/PlumeShaders.cmake)
6+
# plume_shaders_init()
7+
#
8+
# plume_compile_vertex_shader(my_target shaders/main.vert.hlsl mainVert VSMain)
9+
# plume_compile_pixel_shader(my_target shaders/main.frag.hlsl mainFrag PSMain)
10+
# plume_compile_compute_shader(my_target shaders/compute.hlsl computeShader CSMain)
11+
12+
include("${CMAKE_CURRENT_LIST_DIR}/modules/PlumeFileToC.cmake")
13+
include("${CMAKE_CURRENT_LIST_DIR}/modules/PlumeDXC.cmake")
14+
include("${CMAKE_CURRENT_LIST_DIR}/modules/PlumeSpirvCross.cmake")
15+
16+
function(_plume_embed TARGET_NAME INPUT_FILE VAR_NAME OUTPUT_C OUTPUT_H)
17+
plume_build_file_to_c()
18+
19+
get_filename_component(OUT_DIR "${OUTPUT_C}" DIRECTORY)
20+
file(MAKE_DIRECTORY "${OUT_DIR}")
21+
22+
add_custom_command(
23+
OUTPUT "${OUTPUT_C}" "${OUTPUT_H}"
24+
COMMAND plume_file_to_c "${INPUT_FILE}" "${VAR_NAME}" "${OUTPUT_C}" "${OUTPUT_H}"
25+
DEPENDS "${INPUT_FILE}" plume_file_to_c
26+
COMMENT "Embedding ${VAR_NAME} from ${INPUT_FILE}"
27+
VERBATIM
28+
)
29+
30+
target_sources(${TARGET_NAME} PRIVATE "${OUTPUT_C}")
31+
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}")
32+
endfunction()
33+
34+
function(plume_shaders_init)
35+
if(NOT DEFINED PLUME_DXC_EXECUTABLE)
36+
plume_fetch_dxc()
37+
endif()
38+
39+
if(APPLE AND NOT TARGET plume_spirv_cross_msl)
40+
plume_fetch_spirv_cross()
41+
endif()
42+
43+
plume_build_file_to_c()
44+
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/shaders")
45+
endfunction()
46+
47+
function(_plume_compile_hlsl_impl TARGET_NAME SHADER_SOURCE SHADER_TYPE OUTPUT_NAME OUTPUT_FORMAT ENTRY_POINT)
48+
cmake_parse_arguments(PARSE_ARGV 6 ARG "" "SHADER_MODEL;OUTPUT_DIR" "INCLUDE_DIRS;EXTRA_ARGS")
49+
50+
plume_get_dxc_command(DXC_CMD)
51+
52+
if(OUTPUT_FORMAT STREQUAL "spirv")
53+
set(OUTPUT_EXT "spirv")
54+
set(BLOB_SUFFIX "SPIRV")
55+
set(FORMAT_FLAGS ${PLUME_DXC_SPV_OPTS})
56+
elseif(OUTPUT_FORMAT STREQUAL "dxil")
57+
set(OUTPUT_EXT "dxil")
58+
set(BLOB_SUFFIX "DXIL")
59+
set(FORMAT_FLAGS ${PLUME_DXC_DXIL_OPTS})
60+
else()
61+
message(FATAL_ERROR "Unknown output format: ${OUTPUT_FORMAT}")
62+
endif()
63+
64+
set(SHADER_MODEL "6_0")
65+
if(ARG_SHADER_MODEL)
66+
set(SHADER_MODEL "${ARG_SHADER_MODEL}")
67+
endif()
68+
69+
if(ARG_OUTPUT_DIR)
70+
set(OUT_DIR "${ARG_OUTPUT_DIR}")
71+
else()
72+
set(OUT_DIR "${CMAKE_BINARY_DIR}/shaders")
73+
endif()
74+
file(MAKE_DIRECTORY "${OUT_DIR}")
75+
76+
set(PROFILE "")
77+
set(DXC_TYPE_ARGS "")
78+
if(SHADER_TYPE STREQUAL "vertex")
79+
set(PROFILE "vs_${SHADER_MODEL}")
80+
set(DXC_TYPE_ARGS "-fvk-invert-y")
81+
elseif(SHADER_TYPE STREQUAL "pixel" OR SHADER_TYPE STREQUAL "fragment")
82+
set(PROFILE "ps_${SHADER_MODEL}")
83+
elseif(SHADER_TYPE STREQUAL "compute")
84+
set(PROFILE "cs_${SHADER_MODEL}")
85+
elseif(SHADER_TYPE STREQUAL "geometry")
86+
set(PROFILE "gs_${SHADER_MODEL}")
87+
elseif(SHADER_TYPE STREQUAL "library")
88+
set(PROFILE "lib_${SHADER_MODEL}")
89+
else()
90+
message(FATAL_ERROR "Unknown shader type: ${SHADER_TYPE}")
91+
endif()
92+
93+
set(INCLUDE_FLAGS "")
94+
foreach(DIR ${ARG_INCLUDE_DIRS})
95+
list(APPEND INCLUDE_FLAGS "-I${DIR}")
96+
endforeach()
97+
98+
if(ENTRY_POINT STREQUAL "")
99+
set(ENTRY_ARGS "")
100+
else()
101+
set(ENTRY_ARGS "-E" "${ENTRY_POINT}")
102+
endif()
103+
104+
set(OUTPUT_FILE "${OUT_DIR}/${OUTPUT_NAME}.hlsl.${OUTPUT_EXT}")
105+
add_custom_command(
106+
OUTPUT "${OUTPUT_FILE}"
107+
COMMAND ${DXC_CMD}
108+
${PLUME_DXC_COMMON_OPTS}
109+
${INCLUDE_FLAGS}
110+
${DXC_TYPE_ARGS}
111+
${ARG_EXTRA_ARGS}
112+
${ENTRY_ARGS}
113+
-T ${PROFILE}
114+
${FORMAT_FLAGS}
115+
-Fo "${OUTPUT_FILE}"
116+
"${SHADER_SOURCE}"
117+
DEPENDS "${SHADER_SOURCE}"
118+
COMMENT "DXC: ${SHADER_SOURCE} -> ${OUTPUT_EXT}"
119+
VERBATIM
120+
)
121+
122+
set(C_OUTPUT "${OUT_DIR}/${OUTPUT_NAME}.hlsl.${OUTPUT_EXT}.c")
123+
set(H_OUTPUT "${OUT_DIR}/${OUTPUT_NAME}.hlsl.${OUTPUT_EXT}.h")
124+
_plume_embed(${TARGET_NAME} "${OUTPUT_FILE}" "${OUTPUT_NAME}Blob${BLOB_SUFFIX}" "${C_OUTPUT}" "${H_OUTPUT}")
125+
endfunction()
126+
127+
function(_plume_compile_spirv_to_metal_impl TARGET_NAME SPIRV_FILE OUTPUT_NAME)
128+
cmake_parse_arguments(PARSE_ARGV 3 ARG "" "OUTPUT_DIR" "")
129+
130+
if(ARG_OUTPUT_DIR)
131+
set(OUT_DIR "${ARG_OUTPUT_DIR}")
132+
else()
133+
set(OUT_DIR "${CMAKE_BINARY_DIR}/shaders")
134+
endif()
135+
file(MAKE_DIRECTORY "${OUT_DIR}")
136+
137+
set(METAL_SOURCE "${OUT_DIR}/${OUTPUT_NAME}.hlsl.metal")
138+
set(IR_OUTPUT "${OUT_DIR}/${OUTPUT_NAME}.hlsl.ir")
139+
set(METALLIB_OUTPUT "${OUT_DIR}/${OUTPUT_NAME}.hlsl.metallib")
140+
set(C_OUTPUT "${OUT_DIR}/${OUTPUT_NAME}.hlsl.metal.c")
141+
set(H_OUTPUT "${OUT_DIR}/${OUTPUT_NAME}.hlsl.metal.h")
142+
143+
if(CMAKE_OSX_DEPLOYMENT_TARGET)
144+
set(METAL_VERSION_FLAG "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
145+
else()
146+
set(METAL_VERSION_FLAG "")
147+
endif()
148+
149+
add_custom_command(
150+
OUTPUT "${METAL_SOURCE}"
151+
COMMAND plume_spirv_cross_msl "${SPIRV_FILE}" "${METAL_SOURCE}"
152+
DEPENDS "${SPIRV_FILE}" plume_spirv_cross_msl
153+
COMMENT "SPIRV-Cross: ${SPIRV_FILE} -> Metal source"
154+
VERBATIM
155+
)
156+
157+
add_custom_command(
158+
OUTPUT "${IR_OUTPUT}"
159+
COMMAND xcrun -sdk macosx metal ${METAL_VERSION_FLAG} -o "${IR_OUTPUT}" -c "${METAL_SOURCE}"
160+
DEPENDS "${METAL_SOURCE}"
161+
COMMENT "Compiling Metal shader ${OUTPUT_NAME} to IR"
162+
VERBATIM
163+
)
164+
165+
add_custom_command(
166+
OUTPUT "${METALLIB_OUTPUT}"
167+
COMMAND xcrun -sdk macosx metallib "${IR_OUTPUT}" -o "${METALLIB_OUTPUT}"
168+
DEPENDS "${IR_OUTPUT}"
169+
COMMENT "Linking ${OUTPUT_NAME} to metallib"
170+
VERBATIM
171+
)
172+
173+
_plume_embed(${TARGET_NAME} "${METALLIB_OUTPUT}" "${OUTPUT_NAME}BlobMSL"
174+
"${C_OUTPUT}" "${H_OUTPUT}")
175+
endfunction()
176+
177+
function(_plume_compile_metal_impl TARGET_NAME SHADER_SOURCE OUTPUT_NAME)
178+
set(IR_OUTPUT "${CMAKE_BINARY_DIR}/shaders/${OUTPUT_NAME}.ir")
179+
set(METALLIB_OUTPUT "${CMAKE_BINARY_DIR}/shaders/${OUTPUT_NAME}.metallib")
180+
set(C_OUTPUT "${CMAKE_BINARY_DIR}/shaders/${OUTPUT_NAME}.metal.c")
181+
set(H_OUTPUT "${CMAKE_BINARY_DIR}/shaders/${OUTPUT_NAME}.metal.h")
182+
183+
if(CMAKE_OSX_DEPLOYMENT_TARGET)
184+
set(METAL_VERSION_FLAG "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
185+
else()
186+
set(METAL_VERSION_FLAG "")
187+
endif()
188+
189+
add_custom_command(
190+
OUTPUT "${IR_OUTPUT}"
191+
COMMAND xcrun -sdk macosx metal ${METAL_VERSION_FLAG} -o "${IR_OUTPUT}" -c "${SHADER_SOURCE}"
192+
DEPENDS "${SHADER_SOURCE}"
193+
COMMENT "Compiling Metal shader ${OUTPUT_NAME} to IR"
194+
VERBATIM
195+
)
196+
197+
add_custom_command(
198+
OUTPUT "${METALLIB_OUTPUT}"
199+
COMMAND xcrun -sdk macosx metallib "${IR_OUTPUT}" -o "${METALLIB_OUTPUT}"
200+
DEPENDS "${IR_OUTPUT}"
201+
COMMENT "Linking ${OUTPUT_NAME} to metallib"
202+
VERBATIM
203+
)
204+
205+
add_custom_command(
206+
OUTPUT "${C_OUTPUT}" "${H_OUTPUT}"
207+
COMMAND plume_file_to_c "${METALLIB_OUTPUT}" "${OUTPUT_NAME}BlobMSL" "${C_OUTPUT}" "${H_OUTPUT}"
208+
DEPENDS "${METALLIB_OUTPUT}" plume_file_to_c
209+
COMMENT "Generating C header for Metal shader ${OUTPUT_NAME}"
210+
VERBATIM
211+
)
212+
213+
target_sources(${TARGET_NAME} PRIVATE "${C_OUTPUT}")
214+
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}")
215+
endfunction()
216+
217+
# Public API
218+
219+
function(plume_compile_shader TARGET_NAME SHADER_SOURCE SHADER_TYPE OUTPUT_NAME ENTRY_POINT)
220+
cmake_parse_arguments(ARG "SPEC_CONSTANTS" "SHADER_MODEL;OUTPUT_DIR" "INCLUDE_DIRS;EXTRA_ARGS" ${ARGN})
221+
222+
get_filename_component(SHADER_EXT "${SHADER_SOURCE}" EXT)
223+
224+
if(SHADER_EXT MATCHES "\\.metal$")
225+
if(APPLE)
226+
_plume_compile_metal_impl(${TARGET_NAME} "${SHADER_SOURCE}" ${OUTPUT_NAME})
227+
endif()
228+
elseif(SHADER_EXT MATCHES "\\.hlsl$")
229+
set(IMPL_ARGS "")
230+
if(ARG_SHADER_MODEL)
231+
list(APPEND IMPL_ARGS SHADER_MODEL "${ARG_SHADER_MODEL}")
232+
endif()
233+
if(ARG_INCLUDE_DIRS)
234+
list(APPEND IMPL_ARGS INCLUDE_DIRS ${ARG_INCLUDE_DIRS})
235+
endif()
236+
if(ARG_EXTRA_ARGS)
237+
list(APPEND IMPL_ARGS EXTRA_ARGS ${ARG_EXTRA_ARGS})
238+
endif()
239+
if(ARG_OUTPUT_DIR)
240+
list(APPEND IMPL_ARGS OUTPUT_DIR "${ARG_OUTPUT_DIR}")
241+
set(OUT_DIR "${ARG_OUTPUT_DIR}")
242+
else()
243+
set(OUT_DIR "${CMAKE_BINARY_DIR}/shaders")
244+
endif()
245+
246+
_plume_compile_hlsl_impl(${TARGET_NAME} "${SHADER_SOURCE}" ${SHADER_TYPE} ${OUTPUT_NAME} "spirv" ${ENTRY_POINT} ${IMPL_ARGS})
247+
248+
if(WIN32 AND NOT ARG_SPEC_CONSTANTS)
249+
_plume_compile_hlsl_impl(${TARGET_NAME} "${SHADER_SOURCE}" ${SHADER_TYPE} ${OUTPUT_NAME} "dxil" ${ENTRY_POINT} ${IMPL_ARGS})
250+
endif()
251+
252+
if(APPLE AND TARGET plume_spirv_cross_msl)
253+
set(SPIRV_FILE "${OUT_DIR}/${OUTPUT_NAME}.hlsl.spirv")
254+
_plume_compile_spirv_to_metal_impl(${TARGET_NAME} "${SPIRV_FILE}" ${OUTPUT_NAME} OUTPUT_DIR "${OUT_DIR}")
255+
endif()
256+
else()
257+
message(WARNING "Unsupported shader extension '${SHADER_EXT}' for ${SHADER_SOURCE}. Use .hlsl or .metal")
258+
endif()
259+
endfunction()
260+
261+
function(plume_compile_vertex_shader TARGET_NAME SHADER_SOURCE OUTPUT_NAME ENTRY_POINT)
262+
plume_compile_shader(${TARGET_NAME} "${SHADER_SOURCE}" "vertex" ${OUTPUT_NAME} ${ENTRY_POINT} ${ARGN})
263+
endfunction()
264+
265+
function(plume_compile_pixel_shader TARGET_NAME SHADER_SOURCE OUTPUT_NAME ENTRY_POINT)
266+
plume_compile_shader(${TARGET_NAME} "${SHADER_SOURCE}" "pixel" ${OUTPUT_NAME} ${ENTRY_POINT} ${ARGN})
267+
endfunction()
268+
269+
function(plume_compile_compute_shader TARGET_NAME SHADER_SOURCE OUTPUT_NAME ENTRY_POINT)
270+
plume_compile_shader(${TARGET_NAME} "${SHADER_SOURCE}" "compute" ${OUTPUT_NAME} ${ENTRY_POINT} ${ARGN})
271+
endfunction()
272+
273+
function(plume_compile_geometry_shader TARGET_NAME SHADER_SOURCE OUTPUT_NAME ENTRY_POINT)
274+
plume_compile_shader(${TARGET_NAME} "${SHADER_SOURCE}" "geometry" ${OUTPUT_NAME} ${ENTRY_POINT} ${ARGN})
275+
endfunction()
File renamed without changes.

0 commit comments

Comments
 (0)