Archived
1
Fork 0

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:
Joshua Goins 2022-02-21 18:07:22 -05:00
parent e03d0eceac
commit e1c688bea7
7 changed files with 71 additions and 44 deletions

View file

@ -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))

View file

@ -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)

View file

@ -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)

View file

@ -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 {};
}

View file

@ -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)

View file

@ -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

View file

@ -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;