Skip to content

Commit

Permalink
Compile shaders at build time
Browse files Browse the repository at this point in the history
  • Loading branch information
andrejnau committed Jan 21, 2024
1 parent cf546e6 commit f870f3a
Show file tree
Hide file tree
Showing 11 changed files with 186 additions and 6 deletions.
11 changes: 11 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,14 @@ if (BUILD_TESTING)
endif()

add_subdirectory(src)

if (CMAKE_CROSSCOMPILING AND IOS_OR_TVOS AND BUILD_SAMPLES)
execute_process(
COMMAND "${CMAKE_COMMAND}" "${CMAKE_CURRENT_SOURCE_DIR}" -BmacOS
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
execute_process(
COMMAND "${CMAKE_COMMAND}" --build macOS --config Release --target ShaderCompilerCLI -j 16
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
endif()
26 changes: 26 additions & 0 deletions cmake/compile_shaders.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
function(compile_shaders target shaders output)
if (CMAKE_CROSSCOMPILING AND IOS_OR_TVOS)
set(shader_compiler_cli "${CMAKE_BINARY_DIR}/macOS/bin/ShaderCompilerCLI")
else()
set(shader_compiler_cli "$<TARGET_FILE:ShaderCompilerCLI>")
endif()
set(output_dir "${CMAKE_BINARY_DIR}/gen/${target}/")
foreach(full_shader_path ${shaders})
get_filename_component(shader_name ${full_shader_path} NAME_WE)
set(spirv ${output_dir}/${shader_name}.spirv)
set(dxil ${output_dir}/${shader_name}.dxil)
get_property(entrypoint SOURCE ${full_shader_path} PROPERTY SHADER_ENTRYPOINT)
get_property(type SOURCE ${full_shader_path} PROPERTY SHADER_TYPE)
get_property(model SOURCE ${full_shader_path} PROPERTY SHADER_MODEL)
add_custom_command(OUTPUT ${spirv} ${dxil}
COMMAND ${CMAKE_COMMAND} -E echo ${shader_name} ${full_shader_path} ${entrypoint} ${type} ${model} ${output_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${output_dir}
COMMAND ${shader_compiler_cli} ${shader_name} ${full_shader_path} ${entrypoint} ${type} ${model} ${output_dir}
DEPENDS ShaderCompilerCLI
MAIN_DEPENDENCY "${full_shader_path}"
)
set(compiled_shaders ${compiled_shaders} ${spirv})
set(compiled_shaders ${compiled_shaders} ${dxil})
endforeach()
set(${output} ${compiled_shaders} PARENT_SCOPE)
endfunction()
22 changes: 18 additions & 4 deletions src/Apps/Triangle/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,32 @@ list(APPEND sources
main.mm
)

list(APPEND resources
PixelShader.spv
VertexShader.spv
set(shaders_path "${assets_path}/shaders/CoreTriangle")

set(pixel_shaders
${shaders_path}/PixelShader.hlsl
)
set(vertex_shaders
${shaders_path}/VertexShader.hlsl
)

set_property(SOURCE ${vertex_shaders} ${pixel_shaders} PROPERTY SHADER_ENTRYPOINT main)
set_property(SOURCE ${vertex_shaders} ${pixel_shaders} PROPERTY SHADER_MODEL 6_0)
set_property(SOURCE ${vertex_shaders} PROPERTY SHADER_TYPE Vertex)
set_property(SOURCE ${pixel_shaders} PROPERTY SHADER_TYPE Pixel)

set(shaders_files ${pixel_shaders} ${vertex_shaders})

include(compile_shaders)
compile_shaders(Triangle "${shaders_files}" resources)

set_source_files_properties(${resources} PROPERTIES
MACOSX_PACKAGE_LOCATION Resources
)

add_executable(Triangle MACOSX_BUNDLE
${sources}
${resources}
${sources}
)

target_link_libraries(Triangle
Expand Down
Binary file removed src/Apps/Triangle/PixelShader.spv
Binary file not shown.
Binary file removed src/Apps/Triangle/VertexShader.spv
Binary file not shown.
4 changes: 2 additions & 2 deletions src/Apps/Triangle/main.mm
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@
constant_buffer->CommitMemory(MemoryType::kUpload);
constant_buffer->UpdateUploadBuffer(0, &constant_data, sizeof(constant_data));

auto vertex_path = [[NSBundle mainBundle] pathForResource:@"VertexShader" ofType:@"spv"];
auto pixel_path = [[NSBundle mainBundle] pathForResource:@"PixelShader" ofType:@"spv"];
auto vertex_path = [[NSBundle mainBundle] pathForResource:@"VertexShader" ofType:@"spirv"];
auto pixel_path = [[NSBundle mainBundle] pathForResource:@"PixelShader" ofType:@"spirv"];
vertex_shader =
device->CreateShader(ReadBinaryFile([vertex_path UTF8String]), ShaderBlobType::kSPIRV, ShaderType::kVertex);
pixel_shader =
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
if (BUILD_SAMPLES)
add_subdirectory(Apps)
add_subdirectory(Modules)
add_subdirectory(Tools)
endif()

add_subdirectory(FlyCube)
2 changes: 2 additions & 0 deletions src/FlyCube/Instance/BaseTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ struct ShaderDesc {
std::string model;
std::map<std::string, std::string> define;

ShaderDesc() = default;

ShaderDesc(const std::string& shader_path, const std::string& entrypoint, ShaderType type, const std::string& model)
: shader_path(shader_path)
, entrypoint(entrypoint)
Expand Down
1 change: 1 addition & 0 deletions src/Tools/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_subdirectory(ShaderCompilerCLI)
24 changes: 24 additions & 0 deletions src/Tools/ShaderCompilerCLI/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
if (CMAKE_CROSSCOMPILING)
return()
endif()

add_executable(ShaderCompilerCLI
${project_root}/src/FlyCube/HLSLCompiler/Compiler.cpp
${project_root}/src/FlyCube/HLSLCompiler/DXCLoader.cpp
${project_root}/src/FlyCube/Utilities/SystemUtils.cpp
main.cpp
)

target_link_libraries(ShaderCompilerCLI
dxc
gli
glm
nowide
)

target_include_directories(ShaderCompilerCLI
PUBLIC
"${project_root}/src/FlyCube"
)

set_target_properties(ShaderCompilerCLI PROPERTIES FOLDER "Tools")
101 changes: 101 additions & 0 deletions src/Tools/ShaderCompilerCLI/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include "HLSLCompiler/Compiler.h"
#include "Instance/BaseTypes.h"

#include <cassert>
#include <fstream>

namespace {

ShaderType GetShaderType(const std::string& target)
{
if (target == "Pixel") {
return ShaderType::kPixel;
} else if (target == "Vertex") {
return ShaderType::kVertex;
} else if (target == "Compute") {
return ShaderType::kCompute;
} else if (target == "Geometry") {
return ShaderType::kGeometry;
} else if (target == "Amplification") {
return ShaderType::kAmplification;
} else if (target == "Mesh") {
return ShaderType::kMesh;
} else if (target == "Library") {
return ShaderType::kLibrary;
}
assert(false);
return ShaderType::kUnknown;
}

std::string GetShaderExtension(ShaderBlobType shader_type)
{
switch (shader_type) {
case ShaderBlobType::kDXIL:
return ".dxil";
case ShaderBlobType::kSPIRV:
return ".spirv";
default:
assert(false);
return ".blob";
}
}

void CompileShader(const std::string& shader_name,
const ShaderDesc& desc,
const std::string& output_path,
ShaderBlobType shader_type)
{
std::string path = output_path + "/" + shader_name + GetShaderExtension(shader_type);
std::vector<uint8_t> blob = Compile(desc, shader_type);
std::fstream file(path, std::ios::out | std::ios::binary);
file.write(reinterpret_cast<char*>(blob.data()), blob.size());
}

} // namespace

class ParseCmd {
public:
ParseCmd(int argc, char* argv[])
{
size_t arg_index = 0;
auto get_next_arg = [&] {
++arg_index;
assert(arg_index < argc);
return argv[arg_index];
};
m_shader_name = get_next_arg();
m_desc.shader_path = get_next_arg();
m_desc.entrypoint = get_next_arg();
m_desc.type = GetShaderType(get_next_arg());
m_desc.model = get_next_arg();
m_output_dir = get_next_arg();
}

const std::string& GetShaderName() const
{
return m_shader_name;
}

const ShaderDesc& GetShaderDesc() const
{
return m_desc;
}

const std::string& GetOutputDir() const
{
return m_output_dir;
}

private:
std::string m_shader_name;
ShaderDesc m_desc;
std::string m_output_dir;
};

int main(int argc, char* argv[])
{
ParseCmd cmd(argc, argv);
CompileShader(cmd.GetShaderName(), cmd.GetShaderDesc(), cmd.GetOutputDir(), ShaderBlobType::kDXIL);
CompileShader(cmd.GetShaderName(), cmd.GetShaderDesc(), cmd.GetOutputDir(), ShaderBlobType::kSPIRV);
return 0;
}

0 comments on commit f870f3a

Please sign in to comment.