Completely overhaul shader generation, again
Now it's even simpler, and it now generates multiple shader languages at once! The copying mechanism is now much simpler on non-mac platforms as well. HLSL is also now a supported shader target language.
This commit is contained in:
parent
e03d0eceac
commit
e1c688bea7
7 changed files with 71 additions and 44 deletions
|
@ -25,7 +25,6 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
|||
set(ENABLE_LINUX TRUE)
|
||||
|
||||
set(NEEDS_HOSTED_SHADER_COMPILER FALSE)
|
||||
set(REQUIRED_SHADER_LANGUAGE "spirv")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" AND NOT IOS)
|
||||
|
@ -40,7 +39,6 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" AND NOT IOS)
|
|||
|
||||
set(CMAKE_XCODE_GENERATE_SCHEME OFF)
|
||||
set(NEEDS_HOSTED_SHADER_COMPILER FALSE)
|
||||
set(REQUIRED_SHADER_LANGUAGE "msl")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
|
||||
|
@ -52,7 +50,6 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
|
|||
set(ENABLE_METAL TRUE)
|
||||
|
||||
set(NEEDS_HOSTED_SHADER_COMPILER TRUE)
|
||||
set(REQUIRED_SHADER_LANGUAGE "msl")
|
||||
set(EXTRA_PLATFORM_ARG "mobile")
|
||||
endif()
|
||||
|
||||
|
@ -65,7 +62,6 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "tvOS")
|
|||
set(ENABLE_METAL TRUE)
|
||||
|
||||
set(NEEDS_HOSTED_SHADER_COMPILER TRUE)
|
||||
set(REQUIRED_SHADER_LANGUAGE "msl")
|
||||
set(EXTRA_PLATFORM_ARG "mobile")
|
||||
endif()
|
||||
|
||||
|
@ -79,7 +75,6 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
|||
set(ENABLE_DX12 TRUE)
|
||||
|
||||
set(NEEDS_HOSTED_SHADER_COMPILER FALSE)
|
||||
set(REQUIRED_SHADER_LANGUAGE "spirv")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsStore")
|
||||
|
@ -98,11 +93,23 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
|
|||
set(ENABLE_WEBGPU TRUE)
|
||||
|
||||
set(NEEDS_HOSTED_SHADER_COMPILER TRUE)
|
||||
set(REQUIRED_SHADER_LANGUAGE "wgsl")
|
||||
endif()
|
||||
|
||||
if(ENABLE_VULKAN)
|
||||
find_package(Vulkan REQUIRED)
|
||||
list(APPEND SHADER_LANGUAGES "spv")
|
||||
endif()
|
||||
|
||||
if(ENABLE_DX12)
|
||||
list(APPEND SHADER_LANGUAGES "hlsl")
|
||||
endif()
|
||||
|
||||
if(ENABLE_WEBGPU)
|
||||
list(APPEND SHADER_LANGUAGES "wgsl")
|
||||
endif()
|
||||
|
||||
if(ENABLE_METAL)
|
||||
list(APPEND SHADER_LANGUAGES "msl")
|
||||
endif()
|
||||
|
||||
if(NEEDS_HOSTED_SHADER_COMPILER AND (NOT DEFINED SHADER_COMPILER_LOCATION))
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
# add custom command to output compiled shader
|
||||
function(add_shader_command)
|
||||
cmake_parse_arguments(ARGS "" "FILENAME;OUT" "" ${ARGN})
|
||||
cmake_parse_arguments(ARGS "" "FILENAME;OUT;LANG" "" ${ARGN})
|
||||
|
||||
cmake_path(REMOVE_EXTENSION ARGS_FILENAME LAST_ONLY OUTPUT_VARIABLE FILENAME_WITHOUT_EXT)
|
||||
|
||||
set(SRC_FILENAME ${CMAKE_CURRENT_SOURCE_DIR}/${ARGS_FILENAME})
|
||||
set(OUTPUT_FILENAME ${CMAKE_BINARY_DIR}/${FILENAME_WITHOUT_EXT})
|
||||
set(OUTPUT_FILENAME ${CMAKE_BINARY_DIR}/bin/${FILENAME_WITHOUT_EXT}.${ARGS_LANG})
|
||||
|
||||
message(${SRC_FILENAME})
|
||||
message("new output filename " .. ${OUTPUT_FILENAME})
|
||||
|
||||
if(NEEDS_HOSTED_SHADER_COMPILER)
|
||||
set(SHADER_COMPILER_COMMAND ${SHADER_COMPILER_LOCATION})
|
||||
|
@ -13,19 +16,14 @@ function(add_shader_command)
|
|||
set(SHADER_COMPILER_COMMAND $<TARGET_FILE:ShaderCompilerTool>)
|
||||
endif()
|
||||
|
||||
# we want to remove the .nocompile extension just like the tool does, if it exists
|
||||
cmake_path(GET FILENAME_WITHOUT_EXT EXTENSION LAST_ONLY LAST_EXT)
|
||||
|
||||
if(LAST_EXT STREQUAL ".nocompile")
|
||||
cmake_path(REPLACE_EXTENSION OUTPUT_FILENAME LAST_ONLY glsl)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${OUTPUT_FILENAME}
|
||||
COMMAND ${SHADER_COMPILER_COMMAND} ${SRC_FILENAME} ${OUTPUT_FILENAME} ${REQUIRED_SHADER_LANGUAGE} ${EXTRA_PLATFORM_ARG}
|
||||
COMMAND ${SHADER_COMPILER_COMMAND} ${SRC_FILENAME} ${OUTPUT_FILENAME} ${ARGS_LANG} ${EXTRA_PLATFORM_ARG}
|
||||
DEPENDS ${SRC_FILENAME}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/shaders)
|
||||
|
||||
message(${SRC_FILENAME})
|
||||
|
||||
# return the actual filename
|
||||
set(${ARGS_OUT} ${OUTPUT_FILENAME} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
@ -34,14 +32,26 @@ endfunction()
|
|||
function(add_shaders)
|
||||
cmake_parse_arguments(ARGS "" "TARGET" "SHADERS" ${ARGN})
|
||||
|
||||
foreach(SHADER_LANG ${SHADER_LANGUAGES})
|
||||
message(${SHADER_LANG})
|
||||
foreach(SHADER_FILENAME ${ARGS_SHADERS})
|
||||
cmake_path(REMOVE_EXTENSION SHADER_FILENAME LAST_ONLY OUTPUT_VARIABLE FILENAME_WITHOUT_EXT)
|
||||
|
||||
add_shader_command(FILENAME ${SHADER_FILENAME} OUT DST_FILENAME)
|
||||
# we want to remove the .nocompile extension just like the tool does, if it exists
|
||||
cmake_path(GET FILENAME_WITHOUT_EXT EXTENSION LAST_ONLY LAST_EXT)
|
||||
|
||||
set(NEW_SHADER_LANG ${SHADER_LANG})
|
||||
if(LAST_EXT STREQUAL ".nocompile")
|
||||
set(NEW_SHADER_LANG glsl)
|
||||
cmake_path(REPLACE_EXTENSION FILENAME_WITHOUT_EXT LAST_ONLY glsl)
|
||||
endif()
|
||||
|
||||
add_shader_command(FILENAME ${SHADER_FILENAME} OUT DST_FILENAME LANG ${NEW_SHADER_LANG})
|
||||
|
||||
list(APPEND SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${SHADER_FILENAME})
|
||||
list(APPEND DST_FILES ${DST_FILENAME})
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
if(NOT NEEDS_HOSTED_SHADER_COMPILER)
|
||||
add_custom_target(BuildShaders DEPENDS ShaderCompilerTool ${DST_FILES})
|
||||
|
@ -49,8 +59,10 @@ function(add_shaders)
|
|||
add_custom_target(BuildShaders DEPENDS ${DST_FILES})
|
||||
endif()
|
||||
|
||||
message(${DST_FILES})
|
||||
|
||||
add_dependencies(${ARGS_TARGET} BuildShaders)
|
||||
endfunction()
|
||||
|
||||
# make the shader directory if it doesnt exist already
|
||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/shaders)
|
||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/shaders)
|
||||
|
|
|
@ -15,6 +15,7 @@ target_link_libraries(ShaderCompiler
|
|||
spirv-cross-core
|
||||
spirv-cross-glsl
|
||||
spirv-cross-msl
|
||||
spirv-cross-hlsl
|
||||
glslang
|
||||
SPIRV)
|
||||
target_include_directories(ShaderCompiler PUBLIC include PRIVATE src)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "string_utils.hpp"
|
||||
#include "includer.hpp"
|
||||
#include "defaultresources.hpp"
|
||||
#include "spirv_hlsl.hpp"
|
||||
|
||||
static inline std::vector<std::string> include_path;
|
||||
|
||||
|
@ -132,9 +133,16 @@ std::optional<ShaderSource> ShaderCompiler::compile(const ShaderLanguage from_la
|
|||
|
||||
return ShaderSource(msl.compile());
|
||||
}
|
||||
case ShaderLanguage::HLSL:
|
||||
prism::log("Unimplemented shader language: HLSL");
|
||||
return ShaderSource(spirv);
|
||||
case ShaderLanguage::HLSL: {
|
||||
spirv_cross::CompilerHLSL hlsl(std::move(spirv));
|
||||
|
||||
spirv_cross::CompilerHLSL::Options opts;
|
||||
opts.shader_model = 60;
|
||||
|
||||
hlsl.set_hlsl_options(opts);
|
||||
|
||||
return ShaderSource(hlsl.compile());
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
|
2
extern/CMakeLists.txt
vendored
2
extern/CMakeLists.txt
vendored
|
@ -44,7 +44,7 @@ set(SPIRV_CROSS_SKIP_INSTALL ON CACHE BOOL "" FORCE)
|
|||
set(BUILD_EXTERNAL OFF CACHE BOOL "" FORCE)
|
||||
set(SPIRV_CROSS_CLI OFF CACHE BOOL "" FORCE)
|
||||
set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(SPIRV_CROSS_ENABLE_HLSL OFF CACHE BOOL "" FORCE)
|
||||
set(SPIRV_CROSS_ENABLE_HLSL ON CACHE BOOL "" FORCE)
|
||||
set(SPIRV_CROSS_ENABLE_CPP OFF CACHE BOOL "" FORCE)
|
||||
set(SPIRV_CROSS_ENABLE_REFLECT OFF CACHE BOOL "" FORCE)
|
||||
set(SPIRV_CROSS_ENABLE_C_API OFF CACHE BOOL "" FORCE)
|
||||
|
|
|
@ -44,27 +44,18 @@ add_platform(
|
|||
)
|
||||
|
||||
function(add_platform_commands target)
|
||||
# we HAVE to create this dummy target to convince CMake to properly copy over shader files.
|
||||
# before you ask, we have used POST_BUILD before but that only runs if the TARGET specified is built.
|
||||
# when you change a shader source file on disk, BuildShaders is triggered but that doesn't retrigger your actual
|
||||
# app target to be rebuilt, so the shaders are never copied correctly. With this (dumb) system, we ensure they
|
||||
# always are. WHY CMAKE WHY
|
||||
if(ENABLE_MACOS)
|
||||
set(DUMMY_NAME ${target}-CopyShaders)
|
||||
|
||||
add_custom_target(${DUMMY_NAME} ALL DEPENDS ${CMAKE_BINARY_DIR}/${target}-dummy)
|
||||
|
||||
if(ENABLE_MACOS)
|
||||
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${target}-dummy
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${target}>/../Resources/shaders
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/shaders $<TARGET_FILE_DIR:${target}>/../Resources/shaders
|
||||
)
|
||||
else()
|
||||
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${target}-dummy
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${target}>/shaders
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/shaders $<TARGET_FILE_DIR:${target}>/shaders
|
||||
)
|
||||
endif()
|
||||
|
||||
add_dependencies(${target} ${DUMMY_NAME})
|
||||
endif()
|
||||
|
||||
if(NOT SKIP_DATA)
|
||||
add_custom_target(${target}_copy_assets
|
||||
|
|
|
@ -22,7 +22,7 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
ShaderLanguage language = ShaderLanguage::SPIRV;
|
||||
std::string_view shader_language_string = argv[3];
|
||||
if(shader_language_string == "spirv") {
|
||||
if(shader_language_string == "spv") {
|
||||
language = ShaderLanguage::SPIRV;
|
||||
} else if(shader_language_string == "msl") {
|
||||
language = ShaderLanguage::MSL;
|
||||
|
@ -30,6 +30,8 @@ int main(int argc, char* argv[]) {
|
|||
language = ShaderLanguage::WGSL;
|
||||
} else if(shader_language_string == "glsl") {
|
||||
language = ShaderLanguage::GLSL;
|
||||
} else if(shader_language_string == "hlsl") {
|
||||
language = ShaderLanguage::HLSL;
|
||||
}
|
||||
|
||||
CompileOptions options;
|
||||
|
@ -69,13 +71,19 @@ int main(int argc, char* argv[]) {
|
|||
{
|
||||
const auto spirv = compiled_source->as_bytecode();
|
||||
|
||||
std::ofstream out(destination_path.replace_extension(destination_path.extension().string() + ".spv"), std::ios::binary); // remove .glsl
|
||||
std::ofstream out(destination_path, std::ios::binary); // remove .glsl
|
||||
out.write((char*)spirv.data(), spirv.size() * sizeof(uint32_t));
|
||||
}
|
||||
break;
|
||||
case ShaderLanguage::MSL:
|
||||
{
|
||||
std::ofstream out(destination_path.replace_extension(destination_path.extension().string() + ".msl")); // remove .glsl
|
||||
std::ofstream out(destination_path); // remove .glsl
|
||||
out << compiled_source->as_string();
|
||||
}
|
||||
break;
|
||||
case ShaderLanguage::HLSL:
|
||||
{
|
||||
std::ofstream out(destination_path); // remove .glsl
|
||||
out << compiled_source->as_string();
|
||||
}
|
||||
break;
|
||||
|
|
Reference in a new issue