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(ENABLE_LINUX TRUE)
|
||||||
|
|
||||||
set(NEEDS_HOSTED_SHADER_COMPILER FALSE)
|
set(NEEDS_HOSTED_SHADER_COMPILER FALSE)
|
||||||
set(REQUIRED_SHADER_LANGUAGE "spirv")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" AND NOT IOS)
|
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(CMAKE_XCODE_GENERATE_SCHEME OFF)
|
||||||
set(NEEDS_HOSTED_SHADER_COMPILER FALSE)
|
set(NEEDS_HOSTED_SHADER_COMPILER FALSE)
|
||||||
set(REQUIRED_SHADER_LANGUAGE "msl")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
|
||||||
|
@ -52,7 +50,6 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
|
||||||
set(ENABLE_METAL TRUE)
|
set(ENABLE_METAL TRUE)
|
||||||
|
|
||||||
set(NEEDS_HOSTED_SHADER_COMPILER TRUE)
|
set(NEEDS_HOSTED_SHADER_COMPILER TRUE)
|
||||||
set(REQUIRED_SHADER_LANGUAGE "msl")
|
|
||||||
set(EXTRA_PLATFORM_ARG "mobile")
|
set(EXTRA_PLATFORM_ARG "mobile")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -65,7 +62,6 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "tvOS")
|
||||||
set(ENABLE_METAL TRUE)
|
set(ENABLE_METAL TRUE)
|
||||||
|
|
||||||
set(NEEDS_HOSTED_SHADER_COMPILER TRUE)
|
set(NEEDS_HOSTED_SHADER_COMPILER TRUE)
|
||||||
set(REQUIRED_SHADER_LANGUAGE "msl")
|
|
||||||
set(EXTRA_PLATFORM_ARG "mobile")
|
set(EXTRA_PLATFORM_ARG "mobile")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -79,7 +75,6 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||||
set(ENABLE_DX12 TRUE)
|
set(ENABLE_DX12 TRUE)
|
||||||
|
|
||||||
set(NEEDS_HOSTED_SHADER_COMPILER FALSE)
|
set(NEEDS_HOSTED_SHADER_COMPILER FALSE)
|
||||||
set(REQUIRED_SHADER_LANGUAGE "spirv")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsStore")
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "WindowsStore")
|
||||||
|
@ -98,11 +93,23 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
|
||||||
set(ENABLE_WEBGPU TRUE)
|
set(ENABLE_WEBGPU TRUE)
|
||||||
|
|
||||||
set(NEEDS_HOSTED_SHADER_COMPILER TRUE)
|
set(NEEDS_HOSTED_SHADER_COMPILER TRUE)
|
||||||
set(REQUIRED_SHADER_LANGUAGE "wgsl")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_VULKAN)
|
if(ENABLE_VULKAN)
|
||||||
find_package(Vulkan REQUIRED)
|
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()
|
endif()
|
||||||
|
|
||||||
if(NEEDS_HOSTED_SHADER_COMPILER AND (NOT DEFINED SHADER_COMPILER_LOCATION))
|
if(NEEDS_HOSTED_SHADER_COMPILER AND (NOT DEFINED SHADER_COMPILER_LOCATION))
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
# add custom command to output compiled shader
|
# add custom command to output compiled shader
|
||||||
function(add_shader_command)
|
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)
|
cmake_path(REMOVE_EXTENSION ARGS_FILENAME LAST_ONLY OUTPUT_VARIABLE FILENAME_WITHOUT_EXT)
|
||||||
|
|
||||||
set(SRC_FILENAME ${CMAKE_CURRENT_SOURCE_DIR}/${ARGS_FILENAME})
|
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)
|
if(NEEDS_HOSTED_SHADER_COMPILER)
|
||||||
set(SHADER_COMPILER_COMMAND ${SHADER_COMPILER_LOCATION})
|
set(SHADER_COMPILER_COMMAND ${SHADER_COMPILER_LOCATION})
|
||||||
|
@ -13,19 +16,14 @@ function(add_shader_command)
|
||||||
set(SHADER_COMPILER_COMMAND $<TARGET_FILE:ShaderCompilerTool>)
|
set(SHADER_COMPILER_COMMAND $<TARGET_FILE:ShaderCompilerTool>)
|
||||||
endif()
|
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(
|
add_custom_command(
|
||||||
OUTPUT ${OUTPUT_FILENAME}
|
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}
|
DEPENDS ${SRC_FILENAME}
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/shaders)
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/shaders)
|
||||||
|
|
||||||
|
message(${SRC_FILENAME})
|
||||||
|
|
||||||
# return the actual filename
|
# return the actual filename
|
||||||
set(${ARGS_OUT} ${OUTPUT_FILENAME} PARENT_SCOPE)
|
set(${ARGS_OUT} ${OUTPUT_FILENAME} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -34,14 +32,26 @@ endfunction()
|
||||||
function(add_shaders)
|
function(add_shaders)
|
||||||
cmake_parse_arguments(ARGS "" "TARGET" "SHADERS" ${ARGN})
|
cmake_parse_arguments(ARGS "" "TARGET" "SHADERS" ${ARGN})
|
||||||
|
|
||||||
|
foreach(SHADER_LANG ${SHADER_LANGUAGES})
|
||||||
|
message(${SHADER_LANG})
|
||||||
foreach(SHADER_FILENAME ${ARGS_SHADERS})
|
foreach(SHADER_FILENAME ${ARGS_SHADERS})
|
||||||
cmake_path(REMOVE_EXTENSION SHADER_FILENAME LAST_ONLY OUTPUT_VARIABLE FILENAME_WITHOUT_EXT)
|
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 SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${SHADER_FILENAME})
|
||||||
list(APPEND DST_FILES ${DST_FILENAME})
|
list(APPEND DST_FILES ${DST_FILENAME})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
if(NOT NEEDS_HOSTED_SHADER_COMPILER)
|
if(NOT NEEDS_HOSTED_SHADER_COMPILER)
|
||||||
add_custom_target(BuildShaders DEPENDS ShaderCompilerTool ${DST_FILES})
|
add_custom_target(BuildShaders DEPENDS ShaderCompilerTool ${DST_FILES})
|
||||||
|
@ -49,8 +59,10 @@ function(add_shaders)
|
||||||
add_custom_target(BuildShaders DEPENDS ${DST_FILES})
|
add_custom_target(BuildShaders DEPENDS ${DST_FILES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
message(${DST_FILES})
|
||||||
|
|
||||||
add_dependencies(${ARGS_TARGET} BuildShaders)
|
add_dependencies(${ARGS_TARGET} BuildShaders)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# make the shader directory if it doesnt exist already
|
# 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-core
|
||||||
spirv-cross-glsl
|
spirv-cross-glsl
|
||||||
spirv-cross-msl
|
spirv-cross-msl
|
||||||
|
spirv-cross-hlsl
|
||||||
glslang
|
glslang
|
||||||
SPIRV)
|
SPIRV)
|
||||||
target_include_directories(ShaderCompiler PUBLIC include PRIVATE src)
|
target_include_directories(ShaderCompiler PUBLIC include PRIVATE src)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "string_utils.hpp"
|
#include "string_utils.hpp"
|
||||||
#include "includer.hpp"
|
#include "includer.hpp"
|
||||||
#include "defaultresources.hpp"
|
#include "defaultresources.hpp"
|
||||||
|
#include "spirv_hlsl.hpp"
|
||||||
|
|
||||||
static inline std::vector<std::string> include_path;
|
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());
|
return ShaderSource(msl.compile());
|
||||||
}
|
}
|
||||||
case ShaderLanguage::HLSL:
|
case ShaderLanguage::HLSL: {
|
||||||
prism::log("Unimplemented shader language: HLSL");
|
spirv_cross::CompilerHLSL hlsl(std::move(spirv));
|
||||||
return ShaderSource(spirv);
|
|
||||||
|
spirv_cross::CompilerHLSL::Options opts;
|
||||||
|
opts.shader_model = 60;
|
||||||
|
|
||||||
|
hlsl.set_hlsl_options(opts);
|
||||||
|
|
||||||
|
return ShaderSource(hlsl.compile());
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return {};
|
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(BUILD_EXTERNAL OFF CACHE BOOL "" FORCE)
|
||||||
set(SPIRV_CROSS_CLI 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_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_CPP OFF CACHE BOOL "" FORCE)
|
||||||
set(SPIRV_CROSS_ENABLE_REFLECT OFF CACHE BOOL "" FORCE)
|
set(SPIRV_CROSS_ENABLE_REFLECT OFF CACHE BOOL "" FORCE)
|
||||||
set(SPIRV_CROSS_ENABLE_C_API 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)
|
function(add_platform_commands target)
|
||||||
# we HAVE to create this dummy target to convince CMake to properly copy over shader files.
|
if(ENABLE_MACOS)
|
||||||
# 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
|
|
||||||
set(DUMMY_NAME ${target}-CopyShaders)
|
set(DUMMY_NAME ${target}-CopyShaders)
|
||||||
|
|
||||||
add_custom_target(${DUMMY_NAME} ALL DEPENDS ${CMAKE_BINARY_DIR}/${target}-dummy)
|
add_custom_target(${DUMMY_NAME} ALL DEPENDS ${CMAKE_BINARY_DIR}/${target}-dummy)
|
||||||
|
|
||||||
if(ENABLE_MACOS)
|
|
||||||
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${target}-dummy
|
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 make_directory $<TARGET_FILE_DIR:${target}>/../Resources/shaders
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/shaders $<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})
|
add_dependencies(${target} ${DUMMY_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT SKIP_DATA)
|
if(NOT SKIP_DATA)
|
||||||
add_custom_target(${target}_copy_assets
|
add_custom_target(${target}_copy_assets
|
||||||
|
|
|
@ -22,7 +22,7 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
ShaderLanguage language = ShaderLanguage::SPIRV;
|
ShaderLanguage language = ShaderLanguage::SPIRV;
|
||||||
std::string_view shader_language_string = argv[3];
|
std::string_view shader_language_string = argv[3];
|
||||||
if(shader_language_string == "spirv") {
|
if(shader_language_string == "spv") {
|
||||||
language = ShaderLanguage::SPIRV;
|
language = ShaderLanguage::SPIRV;
|
||||||
} else if(shader_language_string == "msl") {
|
} else if(shader_language_string == "msl") {
|
||||||
language = ShaderLanguage::MSL;
|
language = ShaderLanguage::MSL;
|
||||||
|
@ -30,6 +30,8 @@ int main(int argc, char* argv[]) {
|
||||||
language = ShaderLanguage::WGSL;
|
language = ShaderLanguage::WGSL;
|
||||||
} else if(shader_language_string == "glsl") {
|
} else if(shader_language_string == "glsl") {
|
||||||
language = ShaderLanguage::GLSL;
|
language = ShaderLanguage::GLSL;
|
||||||
|
} else if(shader_language_string == "hlsl") {
|
||||||
|
language = ShaderLanguage::HLSL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompileOptions options;
|
CompileOptions options;
|
||||||
|
@ -69,13 +71,19 @@ int main(int argc, char* argv[]) {
|
||||||
{
|
{
|
||||||
const auto spirv = compiled_source->as_bytecode();
|
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));
|
out.write((char*)spirv.data(), spirv.size() * sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ShaderLanguage::MSL:
|
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();
|
out << compiled_source->as_string();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Reference in a new issue