Skip to content

Commit

Permalink
Shader variants (#14)
Browse files Browse the repository at this point in the history
* Use template for target_link_shaders_variant.

* Support multiple macro definitions for target_link_shaders_variant.

* Change name: target_link_shaders_variant -> target_link_shader_variants

* Combined primitive.vert and faceted_primitive.vert.
  • Loading branch information
stripe2933 authored Dec 23, 2024
1 parent 078d876 commit b121192
Show file tree
Hide file tree
Showing 25 changed files with 546 additions and 1,188 deletions.
39 changes: 23 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -198,43 +198,50 @@ endif()
include(cmake/CompileShader.cmake)

target_link_shaders(vk-gltf-viewer
shaders/blend_faceted_primitive.frag
shaders/blend_primitive.frag
shaders/blend_unlit_primitive.frag
shaders/brdfmap.comp
shaders/cubemap_tone_mapping.frag
shaders/cubemap.comp
shaders/depth.frag
shaders/depth.vert
shaders/faceted_primitive.frag
shaders/faceted_primitive.vert
shaders/jump_flood_seed.frag
shaders/jump_flood_seed.vert
shaders/jump_flood.comp
shaders/mask_depth.frag
shaders/mask_depth.vert
shaders/mask_faceted_primitive.frag
shaders/mask_jump_flood_seed.frag
shaders/mask_jump_flood_seed.vert
shaders/mask_primitive.frag
shaders/mask_unlit_primitive.frag
shaders/multiply.comp
shaders/outline.frag
shaders/primitive.frag
shaders/primitive.vert
shaders/screen_quad.vert
shaders/skybox.frag
shaders/skybox.vert
shaders/spherical_harmonic_coefficients_sum.comp
shaders/spherical_harmonics.comp
shaders/unlit_primitive.frag
shaders/unlit_primitive.vert
shaders/weighted_blended_composition.frag
)
target_link_shaders_variant(vk-gltf-viewer
AMD_SHADER_IMAGE_LOAD_STORE_LOD "0;1"
target_link_shader_variants(vk-gltf-viewer
shaders/prefilteredmap.comp
shaders/subgroup_mipmap_16.comp
shaders/subgroup_mipmap_32.comp
shaders/subgroup_mipmap_64.comp
"AMD_SHADER_IMAGE_LOAD_STORE_LOD" 0 1
)
target_link_shader_variants(vk-gltf-viewer
shaders/subgroup_mipmap.comp
"SUBGROUP_SIZE;AMD_SHADER_IMAGE_LOAD_STORE_LOD"
"16 0" "16 1"
"32 0" "32 1"
"64 0" "64 1"
)
target_link_shader_variants(vk-gltf-viewer
shaders/primitive.vert
"FRAGMENT_SHADER_GENERATED_TBN" 0 1
)
target_link_shader_variants(vk-gltf-viewer
shaders/primitive.frag
"FRAGMENT_SHADER_GENERATED_TBN;ALPHA_MODE"
"0 0" "0 1" "0 2"
"1 0" "1 1" "1 2"
)
target_link_shader_variants(vk-gltf-viewer
shaders/unlit_primitive.frag
"ALPHA_MODE" 0 1 2
)
177 changes: 107 additions & 70 deletions cmake/CompileShader.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ function(target_link_shaders TARGET)
cmake_path(GET source FILENAME filename)

# Make source path absolute.
cmake_path(ABSOLUTE_PATH source OUTPUT_VARIABLE source)
cmake_path(ABSOLUTE_PATH source OUTPUT_VARIABLE absolute_source)

# Make shader identifier.
string(MAKE_C_IDENTIFIER ${filename} shader_identifier)

if (${Vulkan_glslc_FOUND})
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm
COMMAND ${Vulkan_GLSLC_EXECUTABLE} -MD -MF shader_depfile/${filename}.d $<$<CONFIG:Release>:-O> --target-env=vulkan1.2 -mfmt=num ${source} -o "shader/${filename}.h"
&& ${CMAKE_COMMAND} -E echo "export module ${target_identifier}:shader.${shader_identifier}\;" > shader/${filename}.cppm
COMMAND ${Vulkan_GLSLC_EXECUTABLE} -MD -MF shader_depfile/${filename}.d $<$<CONFIG:Release>:-O> --target-env=vulkan1.2 -mfmt=num ${absolute_source} -o "shader/${filename}.h"
COMMAND ${CMAKE_COMMAND} -E echo "export module ${target_identifier}:shader.${shader_identifier}\;" > shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E echo "namespace ${target_identifier}::shader { export constexpr unsigned int ${shader_identifier}[] = {" >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E cat shader/${filename}.h >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E rm shader/${filename}.h
&& ${CMAKE_COMMAND} -E echo "}\;}" >> shader/${filename}.cppm
DEPENDS ${source}
DEPENDS ${absolute_source}
BYPRODUCTS shader_depfile/${filename}.d
COMMENT "Compiling SPIR-V: ${source} -> ${filename}.cppm"
DEPFILE shader_depfile/${filename}.d
Expand All @@ -40,13 +40,13 @@ function(target_link_shaders TARGET)
elseif (${Vulkan_glslangValidator_FOUND})
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm
COMMAND ${Vulkan_GLSLANG_VALIDATOR_EXECUTABLE} -V $<$<CONFIG:Debug>:-Od> --target-env vulkan1.2 -x ${source} -o "shader/${filename}.h"
&& ${CMAKE_COMMAND} -E echo "export module ${target_identifier}:shader.${shader_identifier}\;" > shader/${filename}.cppm
COMMAND ${Vulkan_GLSLANG_VALIDATOR_EXECUTABLE} -V $<$<CONFIG:Debug>:-Od> --target-env vulkan1.2 -x ${absolute_source} -o "shader/${filename}.h"
COMMAND ${CMAKE_COMMAND} -E echo "export module ${target_identifier}:shader.${shader_identifier}\;" > shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E echo "namespace ${target_identifier}::shader { export constexpr unsigned int ${shader_identifier}[] = {" >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E cat shader/${filename}.h >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E rm shader/${filename}.h
&& ${CMAKE_COMMAND} -E echo "}\;}" >> shader/${filename}.cppm
DEPENDS ${source}
DEPENDS ${absolute_source}
COMMENT "Compiling SPIR-V: ${source}"
VERBATIM
COMMAND_EXPAND_LISTS
Expand All @@ -59,76 +59,113 @@ function(target_link_shaders TARGET)
target_sources(${TARGET} PRIVATE FILE_SET CXX_MODULES FILES ${outputs})
endfunction()

function(target_link_shaders_variant TARGET MACRO_NAME MACRO_VALUES)
function(target_link_shader_variants TARGET SOURCE MACRO_NAMES)
# Make target identifier.
string(MAKE_C_IDENTIFIER ${TARGET} target_identifier)

set(outputs "")
foreach (source IN LISTS ARGN)
# Get filename from source.
cmake_path(GET source FILENAME filename)

# Make shader identifier.
string(MAKE_C_IDENTIFIER ${filename} shader_identifier)
# Get filename from source.
cmake_path(GET SOURCE FILENAME filename)

# Make shader identifier.
string(MAKE_C_IDENTIFIER ${filename} shader_identifier)

# Make source path absolute.
cmake_path(ABSOLUTE_PATH SOURCE OUTPUT_VARIABLE absolute_source)

add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cpp
# Interface file generation.
COMMAND ${CMAKE_COMMAND} -E echo "export module ${target_identifier}:shader.${shader_identifier}\;" > shader/${filename}.cppm
COMMAND ${CMAKE_COMMAND} -E echo "namespace ${target_identifier}::shader { template <int...> struct ${shader_identifier}_t\;" >> shader/${filename}.cppm
# Implementation file generation.
COMMAND ${CMAKE_COMMAND} -E echo "module ${target_identifier}\;" > shader/${filename}.cpp
COMMAND ${CMAKE_COMMAND} -E echo "import :shader.${shader_identifier}\;" >> shader/${filename}.cpp
COMMENT "Compiling SPIR-V: ${SOURCE}"
VERBATIM
COMMAND_EXPAND_LISTS
)

foreach (macro_values IN LISTS ARGN)
# Split whitespace-delimited string to list.
separate_arguments(macro_values)

# Create CLI macro definitions by zipping the macro names and values.
# e.g. MACRO_NAMES=[MACRO1, MACRO2], macro_values=[0, 1] -> macro_cli_defs="-DMACRO1=0 -DMACRO2=1"
set(macro_cli_defs "")
foreach (macro_name macro_value IN ZIP_LISTS MACRO_NAMES macro_values)
string(APPEND macro_cli_defs "-D${macro_name}=${macro_value} ")
endforeach ()

# Make source path absolute.
cmake_path(ABSOLUTE_PATH source OUTPUT_VARIABLE source)

add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm
COMMAND ${CMAKE_COMMAND} -E echo "export module ${target_identifier}:shader.${shader_identifier}\;" > shader/${filename}.cppm
COMMAND ${CMAKE_COMMAND} -E echo "namespace ${target_identifier}::shader {" >> shader/${filename}.cppm
COMMENT "Compiling SPIR-V: ${source} (${MACRO_NAME}=${MACRO_VALUES})"
VERBATIM
COMMAND_EXPAND_LISTS
)

foreach (macro_value IN LISTS MACRO_VALUES)
# Make variant identifier.
string(MAKE_C_IDENTIFIER "${MACRO_NAME}_${macro_value}" variant_identifier)

if (${Vulkan_glslc_FOUND})
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm
COMMAND ${Vulkan_GLSLC_EXECUTABLE} -MD -MF shader_depfile/${filename}_${variant_identifier}.d $<$<CONFIG:Release>:-O> --target-env=vulkan1.2 -mfmt=num -D${MACRO_NAME}=${macro_value} "${source}" -o shader/${filename}_${variant_identifier}_body.h
&& ${CMAKE_COMMAND} -E echo "export constexpr unsigned int ${shader_identifier}_${variant_identifier}[] = {" >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E cat shader/${filename}_${variant_identifier}_body.h >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E rm shader/${filename}_${variant_identifier}_body.h
&& ${CMAKE_COMMAND} -E echo "}\;" >> shader/${filename}.cppm
DEPENDS "${source}"
BYPRODUCTS shader_depfile/${filename}_${variant_identifier}.d
DEPFILE shader_depfile/${filename}_${variant_identifier}.d
VERBATIM
COMMAND_EXPAND_LISTS
APPEND
)
elseif (${Vulkan_glslangValidator_FOUND})
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm
COMMAND ${Vulkan_GLSLANG_VALIDATOR_EXECUTABLE} -V $<$<CONFIG:Debug>:-Od> --target-env vulkan1.2 -x ${source} -D${MACRO_NAME}=${macro_value} -o shader/${filename}_${variant_identifier}_body.h
&& ${CMAKE_COMMAND} -E echo "export constexpr unsigned int ${shader_identifier}_${variant_identifier}[] = {" >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E cat shader/${filename}_${variant_identifier}_body.h >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E rm shader/${filename}_${variant_identifier}_body.h
&& ${CMAKE_COMMAND} -E echo "}\;" >> shader/${filename}.cppm
DEPENDS "${source}"
VERBATIM
COMMAND_EXPAND_LISTS
APPEND
)
endif ()
# Split whitespace-delimited string to list (to prevent macro_cli_defs are passed with double quotes).
separate_arguments(macro_cli_defs)

endforeach ()
# Make filename-like parameter string.
# e.g., If macro_values=[0, 1], variant_filename="0_1".
list(JOIN macro_values "_" variant_filename)

add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm
COMMAND ${CMAKE_COMMAND} -E echo "}" >> shader/${filename}.cppm
APPEND
VERBATIM
COMMAND_EXPAND_LISTS
)
# Make value parameter string.
# e.g., If macro_values=[0, 1], value_params="0, 1".
list(JOIN macro_values ", " value_params)

list(APPEND outputs ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm)
if (${Vulkan_glslc_FOUND})
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cpp
# Compile GLSL to SPIR-V.
COMMAND ${Vulkan_GLSLC_EXECUTABLE} -MD -MF shader_depfile/${filename}_${variant_filename}.d $<$<CONFIG:Release>:-O> --target-env=vulkan1.2 -mfmt=num ${macro_cli_defs} "${absolute_source}" -o shader/${filename}_${variant_filename}_body.h
# Interface file generation.
COMMAND ${CMAKE_COMMAND} -E echo "template <> struct ${shader_identifier}_t<${value_params}> { static constexpr unsigned int value[] = {" >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E cat shader/${filename}_${variant_filename}_body.h >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E rm shader/${filename}_${variant_filename}_body.h
&& ${CMAKE_COMMAND} -E echo "}\; }\;" >> shader/${filename}.cppm
# Implementation file generation.
COMMAND ${CMAKE_COMMAND} -E echo "extern template struct ${target_identifier}::shader::${shader_identifier}_t<${value_params}>\;" >> shader/${filename}.cpp
DEPENDS "${absolute_source}"
BYPRODUCTS shader_depfile/${filename}_${variant_filename}.d
DEPFILE shader_depfile/${filename}_${variant_filename}.d
VERBATIM
COMMAND_EXPAND_LISTS
APPEND
)
elseif (${Vulkan_glslangValidator_FOUND})
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cpp
# Compile GLSL to SPIR-V.
COMMAND ${Vulkan_GLSLANG_VALIDATOR_EXECUTABLE} -V $<$<CONFIG:Debug>:-Od> --target-env vulkan1.2 -x ${macro_cli_defs} ${absolute_source} -o shader/${filename}_${variant_filename}_body.h
# Interface file generation.
COMMAND ${CMAKE_COMMAND} -E echo "template <> struct ${shader_identifier}_t<${value_params}> { static constexpr unsigned int value[] = {" >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E cat shader/${filename}_${variant_filename}_body.h >> shader/${filename}.cppm
&& ${CMAKE_COMMAND} -E rm shader/${filename}_${variant_filename}_body.h
&& ${CMAKE_COMMAND} -E echo "}\; }\;" >> shader/${filename}.cppm
# Implementation file generation.
COMMAND ${CMAKE_COMMAND} -E echo "extern template struct ${target_identifier}::shader::${shader_identifier}_t<${value_params}>\;" >> shader/${filename}.cpp
DEPENDS "${absolute_source}"
VERBATIM
COMMAND_EXPAND_LISTS
APPEND
)
endif ()
endforeach ()

target_sources(${TARGET} PRIVATE FILE_SET CXX_MODULES FILES ${outputs})
# Make template named type parameters string.
# e.g., If there are 3 macros, template_named_type_params="int MACRO1, int MACRO2, int MACRO3".
set(template_named_type_params "")
foreach (macro_name IN LISTS MACRO_NAMES)
list(APPEND template_named_type_params "int ${macro_name}")
endforeach ()
list(JOIN template_named_type_params ", " template_named_type_params)

# Make named parameter string.
# e.g., If there are 3 macros, name_params="MACRO1, MACRO2, MACRO3".
list(JOIN MACRO_NAMES ", " name_params)

add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm
COMMAND ${CMAKE_COMMAND} -E echo "template <${template_named_type_params}> constexpr auto &${shader_identifier} = ${shader_identifier}_t<${name_params}>::value\; }" >> shader/${filename}.cppm
APPEND
VERBATIM
COMMAND_EXPAND_LISTS
)

target_sources(${TARGET} PRIVATE FILE_SET CXX_MODULES FILES ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cppm)
target_sources(${TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/shader/${filename}.cpp)
endfunction()
12 changes: 5 additions & 7 deletions interface/vulkan/pipeline/BlendPrimitiveRenderer.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ export module vk_gltf_viewer:vulkan.pipeline.BlendPrimitiveRenderer;

import std;
import vku;
import :shader.faceted_primitive_vert;
import :shader.primitive_vert;
import :shader.blend_faceted_primitive_frag;
import :shader.blend_primitive_frag;
import :shader.primitive_frag;
export import :vulkan.pl.Primitive;
export import :vulkan.rp.Scene;

Expand All @@ -21,14 +19,14 @@ namespace vk_gltf_viewer::vulkan::inline pipeline {
device,
vku::Shader {
fragmentShaderTBN
? std::span<const std::uint32_t> { shader::faceted_primitive_vert }
: std::span<const std::uint32_t> { shader::primitive_vert },
? std::span<const std::uint32_t> { shader::primitive_vert<1> }
: std::span<const std::uint32_t> { shader::primitive_vert<0> },
vk::ShaderStageFlagBits::eVertex,
},
vku::Shader {
fragmentShaderTBN
? std::span<const std::uint32_t> { shader::blend_faceted_primitive_frag }
: std::span<const std::uint32_t> { shader::blend_primitive_frag },
? std::span<const std::uint32_t> { shader::primitive_frag<1, 2> }
: std::span<const std::uint32_t> { shader::primitive_frag<0, 2> },
vk::ShaderStageFlagBits::eFragment,
}).get(),
*layout, 1, true, vk::SampleCountFlagBits::e4)
Expand Down
4 changes: 2 additions & 2 deletions interface/vulkan/pipeline/BlendUnlitPrimitiveRenderer.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export module vk_gltf_viewer:vulkan.pipeline.BlendUnlitPrimitiveRenderer;

import vku;
import :shader.unlit_primitive_vert;
import :shader.blend_unlit_primitive_frag;
import :shader.unlit_primitive_frag;
export import :vulkan.pl.Primitive;
export import :vulkan.rp.Scene;

Expand All @@ -16,7 +16,7 @@ namespace vk_gltf_viewer::vulkan::inline pipeline {
createPipelineStages(
device,
vku::Shader { shader::unlit_primitive_vert, vk::ShaderStageFlagBits::eVertex },
vku::Shader { shader::blend_unlit_primitive_frag, vk::ShaderStageFlagBits::eFragment }).get(),
vku::Shader { shader::unlit_primitive_frag<2>, vk::ShaderStageFlagBits::eFragment }).get(),
*layout, 1, true, vk::SampleCountFlagBits::e4)
.setPRasterizationState(vku::unsafeAddress(vk::PipelineRasterizationStateCreateInfo {
{},
Expand Down
12 changes: 5 additions & 7 deletions interface/vulkan/pipeline/MaskPrimitiveRenderer.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ export module vk_gltf_viewer:vulkan.pipeline.MaskPrimitiveRenderer;

import std;
import vku;
import :shader.faceted_primitive_vert;
import :shader.primitive_vert;
import :shader.mask_faceted_primitive_frag;
import :shader.mask_primitive_frag;
import :shader.primitive_frag;
export import :vulkan.pl.Primitive;
export import :vulkan.rp.Scene;

Expand All @@ -21,14 +19,14 @@ namespace vk_gltf_viewer::vulkan::inline pipeline {
device,
vku::Shader {
fragmentShaderTBN
? std::span<const std::uint32_t> { shader::faceted_primitive_vert }
: std::span<const std::uint32_t> { shader::primitive_vert },
? std::span<const std::uint32_t> { shader::primitive_vert<1> }
: std::span<const std::uint32_t> { shader::primitive_vert<0> },
vk::ShaderStageFlagBits::eVertex,
},
vku::Shader {
fragmentShaderTBN
? std::span<const std::uint32_t> { shader::mask_faceted_primitive_frag }
: std::span<const std::uint32_t> { shader::mask_primitive_frag },
? std::span<const std::uint32_t> { shader::primitive_frag<1, 1> }
: std::span<const std::uint32_t> { shader::primitive_frag<0, 1> },
vk::ShaderStageFlagBits::eFragment,
}).get(),
*layout, 1, true, vk::SampleCountFlagBits::e4)
Expand Down
Loading

0 comments on commit b121192

Please sign in to comment.