ENH: Embed shader source in binary.

This commit is contained in:
David Allemang
2023-01-27 09:35:29 -05:00
parent fff18e481f
commit b228f76658
8 changed files with 120 additions and 22 deletions

View File

@@ -4,7 +4,6 @@ project(toddcox-faster)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
include(FetchContent) include(FetchContent)
include(vendor/fmt.cmake) include(vendor/fmt.cmake)
include(vendor/peglib.cmake) include(vendor/peglib.cmake)
include(vendor/glad.cmake) include(vendor/glad.cmake)
@@ -13,6 +12,8 @@ include(vendor/glm.cmake)
include(vendor/gtest.cmake) include(vendor/gtest.cmake)
include(vendor/yaml-cpp.cmake) include(vendor/yaml-cpp.cmake)
include(vendor/embed.cmake)
add_subdirectory(tc) add_subdirectory(tc)
add_subdirectory(vis) add_subdirectory(vis)

85
vendor/embed.cmake vendored Normal file
View File

@@ -0,0 +1,85 @@
find_program(EMBED_LD ${CMAKE_LINKER})
find_program(EMBED_OBJCOPY ${CMAKE_OBJCOPY})
function(_generate_embed_source EMBED_NAME)
set(options)
set(oneValueArgs SOURCE HEADER)
set(multiValueArgs FILES)
cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
set(VIEW_DECLARATIONS)
set(VOID_DECLARATIONS)
set(DEFINITIONS)
foreach (FILE IN LISTS PARSE_FILES)
get_filename_component(FILE_NAME "${FILE}" NAME)
string(MAKE_C_IDENTIFIER "_binary_${FILE}" SYMBOL)
string(MAKE_C_IDENTIFIER "${FILE_NAME}" IDENTIFIER)
string(APPEND VIEW_DECLARATIONS
" /// ${FILE} Text Contents\n"
" extern std::string_view const ${IDENTIFIER};\n")
string(APPEND VOID_DECLARATIONS
" /// ${FILE} Binary Contents\n"
" extern void* const ${IDENTIFIER};\n")
string(APPEND DEFINITIONS
"// ${IDENTIFIER} (${FILE})\n"
"extern \"C\" const char ${SYMBOL}_start[], ${SYMBOL}_end[];\n"
"std::string_view const ${EMBED_NAME}::${IDENTIFIER}(${SYMBOL}_start, ${SYMBOL}_end);\n"
"void* const ${EMBED_NAME}::bin::${IDENTIFIER} = (void *) ${SYMBOL}_start;\n\n")
endforeach ()
file(WRITE "${PARSE_HEADER}"
"#pragma once\n"
"#include <string>\n\n"
"namespace ${EMBED_NAME} {\n${VIEW_DECLARATIONS}}\n\n"
"namespace ${EMBED_NAME}::bin {\n${VOID_DECLARATIONS}}\n")
file(WRITE "${PARSE_SOURCE}"
"#include <${EMBED_NAME}.hpp>\n\n"
"${DEFINITIONS}")
endfunction()
function(_embed_file OUTPUT_OBJECT FILE)
set(OBJECT "${CMAKE_CURRENT_BINARY_DIR}/${FILE}.o")
set(${OUTPUT_OBJECT} ${OBJECT} PARENT_SCOPE)
add_custom_command(
COMMENT "Embedding ${FILE} in ${OBJECT}"
OUTPUT "${FILE}.o" DEPENDS "${FILE}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMAND ${EMBED_LD} -r -o "${OBJECT}" -z noexecstack --format=binary "${FILE}"
COMMAND ${EMBED_OBJCOPY} --rename-section .data=.rodata,alloc,load,readonly,data,contents "${OBJECT}"
VERBATIM
)
endfunction()
function(add_embed_library EMBED_NAME)
set(FILES ${ARGN})
set(EMBED_ROOT ${CMAKE_CURRENT_BINARY_DIR}/_embed/${EMBED_NAME})
set(EMBED_SOURCE "${EMBED_ROOT}/${EMBED_NAME}.cpp")
set(EMBED_INCLUDE "${EMBED_ROOT}/include")
set(EMBED_HEADER "${EMBED_INCLUDE}/${EMBED_NAME}.hpp")
set(OBJECTS)
foreach (FILE ${ARGN})
_embed_file(OBJECT ${FILE})
list(APPEND OBJECTS ${OBJECT})
endforeach ()
message(STATUS "Generating embedding library ${EMBED_NAME}")
_generate_embed_source(
${EMBED_NAME}
SOURCE ${EMBED_SOURCE}
HEADER ${EMBED_HEADER}
FILES ${FILES})
add_library(${EMBED_NAME} STATIC ${OBJECTS} "${EMBED_SOURCE}")
target_include_directories(${EMBED_NAME} PUBLIC "${EMBED_INCLUDE}")
set_target_properties(${EMBED_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
endfunction()

View File

@@ -1,9 +1,11 @@
add_custom_target(shaders ALL DEPENDS shader_output) #add_custom_target(shaders ALL DEPENDS shader_output)
add_custom_command( #add_custom_command(
OUTPUT shader_output # OUTPUT shader_output
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/shaders ${CMAKE_CURRENT_BINARY_DIR}/shaders # COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/shaders ${CMAKE_CURRENT_BINARY_DIR}/shaders
COMMENT "copied shaders" # COMMENT "copied shaders"
) #)
add_subdirectory(shaders)
add_custom_target(presets ALL DEPENDS preset_output) add_custom_target(presets ALL DEPENDS preset_output)
add_custom_command( add_custom_command(
@@ -17,5 +19,5 @@ target_include_directories(vis-util INTERFACE include)
add_executable(vis src/main.cpp) add_executable(vis src/main.cpp)
target_include_directories(vis PRIVATE include) target_include_directories(vis PRIVATE include)
target_link_libraries(vis PRIVATE tc glad glm glfw yaml-cpp) target_link_libraries(vis PRIVATE tc glad glm glfw yaml-cpp shaders)
add_dependencies(vis shaders presets) add_dependencies(vis presets)

View File

@@ -19,7 +19,9 @@ namespace cgl{
glProgramParameteri(id, GL_PROGRAM_SEPARABLE, GL_TRUE); glProgramParameteri(id, GL_PROGRAM_SEPARABLE, GL_TRUE);
} }
ShaderProgram(const std::string &src) : ShaderProgram() { explicit ShaderProgram(const std::string_view &src) : ShaderProgram(std::string(src)) {}
explicit ShaderProgram(const std::string &src) : ShaderProgram() {
Shader<mode> sh(src); Shader<mode> sh(src);
attach(sh); attach(sh);

View File

@@ -0,0 +1,10 @@
add_embed_library(shaders
curve-ortho.gm.glsl
curve-stereo.gm.glsl
diffuse.fs.glsl
direct-ortho.vs.glsl
direct-stereo.vs.glsl
solid.fs.glsl
deferred.vs.glsl
slice.gm.glsl
)

View File

@@ -19,6 +19,8 @@
#include <chrono> #include <chrono>
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include <shaders.hpp>
#ifdef _WIN32 #ifdef _WIN32
extern "C" { extern "C" {
__attribute__((unused)) __declspec(dllexport) int NvOptimusEnablement = 0x00000001; __attribute__((unused)) __declspec(dllexport) int NvOptimusEnablement = 0x00000001;
@@ -155,12 +157,9 @@ struct SliceProp : public Prop<N> {
template<unsigned N> template<unsigned N>
struct SliceRenderer : public Renderer<N> { struct SliceRenderer : public Renderer<N> {
cgl::pgm::vert defer = cgl::pgm::vert::file( cgl::pgm::vert defer = cgl::pgm::vert(shaders::deferred_vs_glsl);
"shaders/slice/deferred.vs.glsl"); cgl::pgm::geom slice = cgl::pgm::geom(shaders::slice_gm_glsl);
cgl::pgm::geom slice = cgl::pgm::geom::file( cgl::pgm::frag solid = cgl::pgm::frag(shaders::solid_fs_glsl);
"shaders/slice/slice.gm.glsl");
cgl::pgm::frag solid = cgl::pgm::frag::file(
"shaders/solid.fs.glsl");
cgl::pipeline pipe; cgl::pipeline pipe;
@@ -193,8 +192,7 @@ template<unsigned N>
struct DirectRenderer : public Renderer<N> { struct DirectRenderer : public Renderer<N> {
cgl::pipeline pipe; cgl::pipeline pipe;
cgl::pgm::frag solid = cgl::pgm::frag::file( cgl::pgm::frag solid = cgl::pgm::frag(shaders::solid_fs_glsl);
"shaders/solid.fs.glsl");
DirectRenderer() { DirectRenderer() {
pipe.stage(solid); pipe.stage(solid);
@@ -255,10 +253,10 @@ void run(const std::string &config_file, GLFWwindow *window) {
SliceRenderer<4> sRen{}; SliceRenderer<4> sRen{};
cgl::pgm::vert o = cgl::pgm::vert::file("shaders/direct-ortho.vs.glsl"); cgl::pgm::vert o = cgl::pgm::vert(shaders::direct_ortho_vs_glsl);
cgl::pgm::vert s = cgl::pgm::vert::file("shaders/direct-stereo.vs.glsl"); cgl::pgm::vert s = cgl::pgm::vert(shaders::direct_stereo_vs_glsl);
cgl::pgm::geom co = cgl::pgm::geom::file("shaders/curve-ortho.gm.glsl"); cgl::pgm::geom co = cgl::pgm::geom(shaders::curve_ortho_gm_glsl);
cgl::pgm::geom cs = cgl::pgm::geom::file("shaders/curve-stereo.gm.glsl"); cgl::pgm::geom cs = cgl::pgm::geom(shaders::curve_stereo_gm_glsl);
DirectRenderer<2> woRen{}; DirectRenderer<2> woRen{};
woRen.pipe.stage(o); woRen.pipe.stage(o);