bkaradzic / bgfx.cmake

CMake build scripts for bgfx. Released under public domain.
Creative Commons Zero v1.0 Universal
197 stars 106 forks source link

Add function bgfx_compile_shader. #237

Closed ZouBoyu closed 1 month ago

ZouBoyu commented 1 month ago

Many projects that use bgfx.cmake still write their own functions to compile shaders, but this is easy to implement.

LIKE:

bgfx_compile_shader(TYPE VERTEX SHADERS vs_cubes.sc VARYING_DEF ${CMAKE_CURRENT_SOURCE_DIR}/varying.def.sc OUTPUT_DIR ${CMAKE_BINARY_DIR})

This function create folders (such as dx11, glsl) and generate [NAME].bin in the folders, matches static bgfx:: ShaderHandle loadShader (bx:: FileReaderI * _deader, const bx::StringView& _name) in bgfx_utils.h

ZouBoyu commented 1 month ago

For reference

function(bgfx_compile_shader)
    set(options "")
    set(oneValueArgs TYPE VARYING_DEF OUTPUT_DIR OUT_FILES_VAR)
    set(multiValueArgs SHADERS INCLUDE_DIRS)
    cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}")

    set(PROFILES 120 300_es spirv)
    if(UNIX AND NOT APPLE)
        set(PLATFORM LINUX)
    elseif(EMSCRIPTEN)
        set(PLATFORM ASM_JS)
    elseif(APPLE)
        set(PLATFORM OSX)
        list(APPEND PROFILES metal)
    elseif(
            WIN32
            OR MINGW
            OR MSYS
            OR CYGWIN
    )
        set(PLATFORM WINDOWS)
        list(APPEND PROFILES s_4_0)
        list(APPEND PROFILES s_5_0)
    else()
        message(error "shaderc: Unsupported platform")
    endif()

    set(ALL_OUTPUTS "")
    foreach(SHADER_FILE ${ARGS_SHADERS})
        source_group("Shaders" FILES "${SHADER}")
        get_filename_component(SHADER_FILE_BASENAME ${SHADER_FILE} NAME)
        get_filename_component(SHADER_FILE_ABSOLUTE ${SHADER_FILE} ABSOLUTE)

        # Build output targets and their commands
        set(OUTPUTS "")
        set(COMMANDS "")
        set(MKDIR_COMMANDS "")
        foreach(PROFILE ${PROFILES})
            _bgfx_get_profile_ext(${PROFILE} PROFILE_EXT)
            set(OUTPUT ${ARGS_OUTPUT_DIR}/${PROFILE_EXT}/${SHADER_FILE_BASENAME}.bin)
            set(PLATFORM_I ${PLATFORM})
            if(PROFILE STREQUAL "spirv")
                set(PLATFORM_I LINUX)
            endif()
            _bgfx_shaderc_parse(
                    CLI #
                    ${ARGS_TYPE} ${PLATFORM_I} WERROR "$<$<CONFIG:debug>:DEBUG>$<$<CONFIG:relwithdebinfo>:DEBUG>"
                    FILE ${SHADER_FILE_ABSOLUTE}
                    OUTPUT ${OUTPUT}
                    PROFILE ${PROFILE}
                    O "$<$<CONFIG:debug>:0>$<$<CONFIG:release>:3>$<$<CONFIG:relwithdebinfo>:3>$<$<CONFIG:minsizerel>:3>"
                    VARYINGDEF ${ARGS_VARYING_DEF}
                    INCLUDES ${BGFX_SHADER_INCLUDE_PATH} ${ARGS_INCLUDE_DIRS}
            )
            list(APPEND OUTPUTS ${OUTPUT})
            list(APPEND ALL_OUTPUTS ${OUTPUT})
            list(APPEND MKDIR_COMMANDS COMMAND ${CMAKE_COMMAND} -E make_directory ${ARGS_OUTPUT_DIR}/${PROFILE_EXT})
            list(APPEND COMMANDS COMMAND bgfx::shaderc ${CLI})
        endforeach()

        add_custom_command(
                OUTPUT ${OUTPUTS}
                COMMAND ${MKDIR_COMMANDS} ${COMMANDS}
                MAIN_DEPENDENCY ${SHADER_FILE_ABSOLUTE}
                DEPENDS ${ARGS_VARYING_DEF}
        )
    endforeach()

    if(DEFINED ARGS_OUT_FILES_VAR)
        set(${ARGS_OUT_FILES_VAR} ${ALL_OUTPUTS} PARENT_SCOPE)
    endif()
endfunction()
ZouBoyu commented 1 month ago

get_filename_component(SHADER_FILE_BASENAME ${SHADER_FILE} NAME)

NAME should be replaced with NAME_WE

bwrsandman commented 1 month ago

Sounds to me that you could change bgfx_compile_shader_to_header into a more general form as bgfx_compile_shader. I'm not sure I see the point of PROFILE_EXT being a directory structure. Maybe it should be more configurable in the args provided. Is there a bgfx macro that requires this?

So I wouldn't mind replacing bgfx_compile_shader_to_header with a bgfx_compile_shader that can both do bin2c and straight binaries. It should be as generic as possible.

bwrsandman commented 1 month ago

Or provide two functions with shared code.

bwrsandman commented 1 month ago

I drafted a change like this but did not include any output path changes (other than removing .h) Let me know if it suits you. For the different way of differentiating the profiles (filenames vs. directories), I think it should be handled separately in another issue.

bwrsandman commented 1 month ago

This function create folders (such as dx11, glsl) and generate [NAME].bin in the folders, matches static bgfx:: ShaderHandle loadShader (bx:: FileReaderI * _deader, const bx::StringView& _name) in bgfx_utils.h

I see now that the directory structure is part of the API

ZouBoyu commented 1 month ago

Thanks. It's OK 🤝