diff --git a/3rdparty/boost/CMakeLists.txt b/3rdparty/boost/CMakeLists.txt index 3c95234b8e..1e7189fce1 100644 --- a/3rdparty/boost/CMakeLists.txt +++ b/3rdparty/boost/CMakeLists.txt @@ -110,11 +110,25 @@ add_subdirectory(superproject/libs/wave EXCLUDE_FROM_ALL) list(APPEND NBL_BOOST_TARGETS boost_wave) # wave foreach(BOOST_LIB IN LISTS NBL_BOOST_LIBS) - if(TARGET boost_${BOOST_LIB}) # wave's deps - list(APPEND NBL_BOOST_TARGETS boost_${BOOST_LIB}) + set(lib boost_${BOOST_LIB}) + if(TARGET ${lib}) # wave's deps + list(APPEND NBL_BOOST_TARGETS ${lib}) endif() endforeach() +# NOTE: wave *must* be compiled with config definitions, inserting them just before wave +# include will lead to ABI mismatch hence we update the target and let inherit options +target_compile_definitions(boost_wave + PUBLIC BOOST_WAVE_ENABLE_COMMANDLINE_MACROS=1 + PUBLIC BOOST_WAVE_SUPPORT_PRAGMA_ONCE=0 + PUBLIC BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES=1 + PUBLIC BOOST_WAVE_SERIALIZATION=0 + PUBLIC BOOST_WAVE_SUPPORT_INCLUDE_NEXT=0 + + # threading option: https://github.com/boostorg/wave/issues/237#issuecomment-2710251773 + PUBLIC BOOST_WAVE_SUPPORT_THREADING=0 +) + set(NBL_BOOST_TARGETS ${NBL_BOOST_TARGETS} PARENT_SCOPE) \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e29839399..76ddd59870 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,7 +196,7 @@ endif() option(NBL_BUILD_BULLET "Enable Bullet Physics building and integration?" OFF) option(NBL_BUILD_DOCS "Enable building documentation?" OFF) # No one has doxygen installed, plus we dont know when was the last time we generated working doxy and we'll use SphinX in the future option(NBL_ENABLE_PROJECT_JSON_CONFIG_VALIDATION "" ON) -option(NBL_EMBED_BUILTIN_RESOURCES "Embed built-in resources?" ON) +option(NBL_EMBED_BUILTIN_RESOURCES "Embed built-in resources?" OFF) option(NBL_ENABLE_DOCKER_INTEGRATION "Enables docker integration, if client is not found Docker Desktop will be installed" OFF) if (NBL_ENABLE_DOCKER_INTEGRATION) @@ -285,4 +285,5 @@ add_subdirectory(artifacts) option(NBL_CPACK_INCLUDE_EXAMPLES "CPack with examples and media" ON) include(cpack/package) include(build/info) -export(TARGETS ${_NBL_3RDPARTY_TARGETS_} Nabla NAMESPACE Nabla:: APPEND FILE ${NBL_ROOT_PATH_BINARY}/NablaExport.cmake) \ No newline at end of file +export(TARGETS ${_NBL_3RDPARTY_TARGETS_} Nabla NAMESPACE Nabla:: APPEND FILE ${NBL_ROOT_PATH_BINARY}/NablaExport.cmake) +NBL_ADJUST_FOLDERS(nabla) \ No newline at end of file diff --git a/CMakePresets.json b/CMakePresets.json index ae56cf1739..718d886790 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -10,6 +10,7 @@ "name": "ci-configure-base", "hidden": true, "cacheVariables": { + "NBL_EMBED_BUILTIN_RESOURCES": "ON", "NBL_UPDATE_GIT_SUBMODULE": "OFF", "NBL_COMPILE_WITH_CUDA": "OFF", "NBL_BUILD_OPTIX": "OFF", diff --git a/cmake/common.cmake b/cmake/common.cmake index bb34e7979c..122f0b169b 100755 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -22,9 +22,7 @@ include(ProcessorCount) macro(nbl_create_executable_project _EXTRA_SOURCES _EXTRA_OPTIONS _EXTRA_INCLUDES _EXTRA_LIBS) get_filename_component(_NBL_PROJECT_DIRECTORY_ "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE) get_filename_component(EXECUTABLE_NAME ${_NBL_PROJECT_DIRECTORY_} NAME) - string(REGEX REPLACE "^[0-9]+\." "" EXECUTABLE_NAME ${EXECUTABLE_NAME}) string(TOLOWER ${EXECUTABLE_NAME} EXECUTABLE_NAME) - string(MAKE_C_IDENTIFIER ${EXECUTABLE_NAME} EXECUTABLE_NAME) project(${EXECUTABLE_NAME}) set_directory_properties(PROPERTIES VS_STARTUP_PROJECT ${EXECUTABLE_NAME}) @@ -1209,12 +1207,11 @@ macro(NBL_WAIT_FOR SLEEP_DURATION) execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${SLEEP_DURATION}) endmacro() -# helper macro for calling docker, takes args as a list of strings macro(NBL_DOCKER) execute_process(COMMAND ${DOCKER_EXECUTABLE} ${ARGN} RESULT_VARIABLE DOCKER_EXIT_CODE OUTPUT_VARIABLE DOCKER_OUTPUT_VAR - ) + ) endmacro() function(NBL_ADJUST_FOLDERS NS) @@ -1223,9 +1220,423 @@ function(NBL_ADJUST_FOLDERS NS) get_target_property(NBL_FOLDER ${T} FOLDER) if(NBL_FOLDER) - set_target_properties(${T} PROPERTIES FOLDER "nabla/${NS}/${NBL_FOLDER}") + set_target_properties(${T} PROPERTIES FOLDER "${NS}/${NBL_FOLDER}") else() - set_target_properties(${T} PROPERTIES FOLDER "nabla/${NS}") + set_target_properties(${T} PROPERTIES FOLDER "${NS}") + endif() + endforeach() +endfunction() + +function(NBL_PARSE_REQUIRED PREFIX) + set(VARIADIC ${ARGV}) + list(POP_FRONT VARIADIC VARIADIC) + foreach(ARG ${VARIADIC}) + set(V ${PREFIX}_${ARG}) + if(NOT ${V}) + message(FATAL_ERROR "\"${ARG}\" argument missing!") + endif() + endforeach() +endfunction() + +# TODO: could create them in the function as _ properties + +define_property(SOURCE PROPERTY NBL_SPIRV_REGISTERED_INPUT + BRIEF_DOCS "Absolute path to input shader which will be glued with device permutation config caps auto-gen file using #include directive, used as part of NSC compile rule to produce SPIRV output" +) + +define_property(SOURCE PROPERTY NBL_SPIRV_PERMUTATION_CONFIG + BRIEF_DOCS "Absolute path to intermediate config file, used as part of NSC compile rule to produce SPIRV output" + FULL_DOCS "The file is auto-generated at configuration time, contains DeviceConfigCaps struct with permuted device caps after which #include directive glues it with an input shader" +) + +define_property(SOURCE PROPERTY NBL_SPIRV_BINARY_DIR + BRIEF_DOCS "a = NBL_SPIRV_BINARY_DIR/NBL_SPIRV_ACCESS_KEY" +) +define_property(SOURCE PROPERTY NBL_SPIRV_ACCESS_KEY + BRIEF_DOCS "a = NBL_SPIRV_BINARY_DIR/NBL_SPIRV_ACCESS_KEY" +) + +define_property(TARGET PROPERTY NBL_CANONICAL_IDENTIFIERS + BRIEF_DOCS "List of identifiers composed as NBL_SPIRV_BINARY_DIR/KEY" + FULL_DOCS "For a given NBL_SPIRV_BINARY_DIR we define a set of canonical KEYs, each unique given which at runtime one can get SPIRV key to access by the canonical key which may contain special permutation part in character of (.=)(.=)(...)" +) + +define_property(TARGET PROPERTY NBL_SPIRV_OUTPUTS + BRIEF_DOCS "Absolute paths to all s which are part of NSC compile rules" +) + +define_property(TARGET PROPERTY NBL_HEADER_PATH + BRIEF_DOCS "Relative path for auto-gen include file with key getters" +) +define_property(TARGET PROPERTY NBL_HEADER_GENERATED_RULE) + +define_property(TARGET PROPERTY NBL_HEADER_CONTENT + BRIEF_DOCS "Contains NBL_HEADER_PATH's content" +) + +function(NBL_CREATE_NSC_COMPILE_RULES) + set(COMMENT "this code has been autogenerated with Nabla CMake NBL_CREATE_HLSL_COMPILE_RULES utility") + set(DEVICE_CONFIG_VIEW +[=[ + +// -> @COMMENT@! +#ifndef _PERMUTATION_CAPS_AUTO_GEN_GLOBALS_INCLUDED_ +#define _PERMUTATION_CAPS_AUTO_GEN_GLOBALS_INCLUDED_ +#ifdef __HLSL_VERSION +#include +struct DeviceConfigCaps +{ +@CAPS_EVAL@ +}; + +#include "@TARGET_INPUT@" + +#endif // __HLSL_VERSION +#endif // _PERMUTATION_CAPS_AUTO_GEN_GLOBALS_INCLUDED_ +// <- @COMMENT@! + +]=]) + + # would get added by NSC anyway and spam in output + set(REQUIRED_OPTIONS + -HV 202x + -Wno-c++14-extensions + -Wno-gnu-static-float-init + -Wno-c++1z-extensions + -Wno-c++11-extensions + -fvk-use-scalar-layout + -enable-16bit-types + -Zpr + -spirv + -fspv-target-env=vulkan1.3 + ) + + if(NOT NBL_EMBED_BUILTIN_RESOURCES) + list(APPEND REQUIRED_OPTIONS + -I "${NBL_ROOT_PATH}/include" + -I "${NBL_ROOT_PATH}/3rdparty/dxc/dxc/external/SPIRV-Headers/include" + -I "${NBL_ROOT_PATH}/3rdparty/boost/superproject/libs/preprocessor/include" + -I "${NBL_ROOT_PATH_BINARY}/src/nbl/device/include" + ) + endif() + + set(REQUIRED_SINGLE_ARGS TARGET BINARY_DIR OUTPUT_VAR INPUTS INCLUDE NAMESPACE) + cmake_parse_arguments(IMPL "" "${REQUIRED_SINGLE_ARGS}" "COMMON_OPTIONS" ${ARGV}) + NBL_PARSE_REQUIRED(IMPL ${REQUIRED_SINGLE_ARGS}) + + if(NOT TARGET ${IMPL_TARGET}) + add_library(${IMPL_TARGET} INTERFACE) + endif() + + if(IS_ABSOLUTE "${IMPL_INCLUDE}") + message(FATAL_ERROR "INCLUDE argument must be relative path") + endif() + + set_target_properties(${IMPL_TARGET} PROPERTIES NBL_HEADER_PATH "${IMPL_INCLUDE}") + + get_target_property(HEADER_RULE_GENERATED ${IMPL_TARGET} NBL_HEADER_GENERATED_RULE) + if(NOT HEADER_RULE_GENERATED) + set(INCLUDE_DIR "$/${IMPL_TARGET}/.cmake/include") + set(INCLUDE_FILE "${INCLUDE_DIR}/$") + set(INCLUDE_CONTENT $) + + file(GENERATE OUTPUT ${INCLUDE_FILE} + CONTENT ${INCLUDE_CONTENT} + TARGET ${IMPL_TARGET} + ) + + target_include_directories(${IMPL_TARGET} INTERFACE ${INCLUDE_DIR}) + set_target_properties(${IMPL_TARGET} PROPERTIES NBL_HEADER_GENERATED_RULE ON) + + set(HEADER_ITEM_VIEW [=[ +#include "nabla.h" + +]=]) + set_property(TARGET ${IMPL_TARGET} APPEND_STRING PROPERTY NBL_HEADER_CONTENT "${HEADER_ITEM_VIEW}") + endif() + + string(MAKE_C_IDENTIFIER "${IMPL_TARGET}_${IMPL_NAMESPACE}" NS_IMPL_KEYS_PROPERTY) + get_property(NS_IMPL_KEYS_PROPERTY_DEFINED + TARGET ${IMPL_TARGET} + PROPERTY "${NS_IMPL_KEYS_PROPERTY}" + DEFINED + ) + if(NOT NS_IMPL_KEYS_PROPERTY_DEFINED) + set(HEADER_ITEM_VIEW [=[ +namespace @IMPL_NAMESPACE@ { + template + inline const nbl::core::string get_spirv_key(const nbl::video::SPhysicalDeviceLimits& limits, const nbl::video::SPhysicalDeviceFeatures& features); + + template + inline const nbl::core::string get_spirv_key(const nbl::video::ILogicalDevice* device) + { + return get_spirv_key(device->getPhysicalDevice()->getLimits(), device->getEnabledFeatures()); + } +} + +]=]) + string(CONFIGURE "${HEADER_ITEM_VIEW}" HEADER_ITEM_EVAL @ONLY) + set_property(TARGET ${IMPL_TARGET} APPEND_STRING PROPERTY NBL_HEADER_CONTENT "${HEADER_ITEM_EVAL}") + define_property(TARGET PROPERTY "${NS_IMPL_KEYS_PROPERTY}") + endif() + + + string(JSON JSON_LENGTH LENGTH "${IMPL_INPUTS}") + math(EXPR LAST_INDEX "${JSON_LENGTH} - 1") + + set(ALL_OUTPUT_KEYS "") + + foreach(INDEX RANGE ${LAST_INDEX}) + string(JSON INPUT GET "${IMPL_INPUTS}" ${INDEX} INPUT) + string(JSON BASE_KEY GET "${IMPL_INPUTS}" ${INDEX} KEY) + string(JSON COMPILE_OPTIONS_LENGTH LENGTH "${IMPL_INPUTS}" ${INDEX} COMPILE_OPTIONS) + + set(COMPILE_OPTIONS "") + math(EXPR LAST_CO "${COMPILE_OPTIONS_LENGTH} - 1") + foreach(COMP_IDX RANGE 0 ${LAST_CO}) + string(JSON COMP_ITEM GET "${IMPL_INPUTS}" ${INDEX} COMPILE_OPTIONS ${COMP_IDX}) + list(APPEND COMPILE_OPTIONS "${COMP_ITEM}") + endforeach() + + set(DEPENDS_ON "") + string(JSON HAS_DEPENDS TYPE "${IMPL_INPUTS}" ${INDEX} DEPENDS) + if(HAS_DEPENDS STREQUAL "ARRAY") + string(JSON DEPENDS_LENGTH LENGTH "${IMPL_INPUTS}" ${INDEX} DEPENDS) + if(NOT DEPENDS_LENGTH EQUAL 0) + math(EXPR LAST_DEP "${DEPENDS_LENGTH} - 1") + foreach(DEP_IDX RANGE 0 ${LAST_DEP}) + string(JSON DEP_ITEM GET "${IMPL_INPUTS}" ${INDEX} DEPENDS ${DEP_IDX}) + list(APPEND DEPENDS_ON "${DEP_ITEM}") + endforeach() + endif() + endif() + + set(HAS_CAPS FALSE) + set(CAPS_LENGTH 0) + string(JSON CAPS_TYPE TYPE "${IMPL_INPUTS}" ${INDEX} CAPS) + if(CAPS_TYPE STREQUAL "ARRAY") + string(JSON CAPS_LENGTH LENGTH "${IMPL_INPUTS}" ${INDEX} CAPS) + if(NOT CAPS_LENGTH EQUAL 0) + set(HAS_CAPS TRUE) + endif() + endif() + + function(ERROR_WHILE_PARSING_ITEM) + string(JSON ITEM GET "${IMPL_INPUTS}" ${INDEX}) + message(FATAL_ERROR + "While parsing ${IMPL_TARGET}'s NSC compile rule\n${ITEM}\n" + ${ARGV} + ) + endfunction() + + set(CAP_NAMES "") + set(CAP_TYPES "") + if(HAS_CAPS) + math(EXPR LAST_CAP "${CAPS_LENGTH} - 1") + foreach(CAP_IDX RANGE 0 ${LAST_CAP}) + string(JSON CAP_NAME GET "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} name) + string(JSON CAP_TYPE GET "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} type) + + if(NOT CAP_TYPE MATCHES "^(bool|uint16_t|uint32_t|uint64_t)$") + ERROR_WHILE_PARSING_ITEM( + "Invalid CAP type \"${CAP_TYPE}\" for ${CAP_NAME}\n" + "Allowed types are: bool, uint16_t, uint32_t, uint64_t" + ) + endif() + + string(JSON CAP_VALUES_LENGTH LENGTH "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} values) + + set(VALUES "") + math(EXPR LAST_VAL "${CAP_VALUES_LENGTH} - 1") + foreach(VAL_IDX RANGE 0 ${LAST_VAL}) + string(JSON VALUE GET "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} values ${VAL_IDX}) + string(JSON VAL_TYPE TYPE "${IMPL_INPUTS}" ${INDEX} CAPS ${CAP_IDX} values ${VAL_IDX}) + + if(NOT VAL_TYPE STREQUAL "NUMBER") + ERROR_WHILE_PARSING_ITEM( + "Invalid CAP value \"${VALUE}\" for CAP \"${CAP_NAME}\" of type ${CAP_TYPE}\n" + "Use numbers for uint*_t and 0/1 for bools." + ) + endif() + + if(CAP_TYPE STREQUAL "bool") + if(NOT VALUE MATCHES "^[01]$") + ERROR_WHILE_PARSING_ITEM( + "Invalid bool value \"${VALUE}\" for ${CAP_NAME}\n" + "Boolean CAPs can only have values 0 or 1." + ) + endif() + endif() + + list(APPEND VALUES "${VALUE}") + endforeach() + + set(CAP_VALUES_${CAP_IDX} "${VALUES}") + list(APPEND CAP_NAMES "${CAP_NAME}") + list(APPEND CAP_TYPES "${CAP_TYPE}") + endforeach() + endif() + + list(LENGTH CAP_NAMES NUM_CAPS) + + set(TARGET_INPUT "${INPUT}") + if(NOT IS_ABSOLUTE "${TARGET_INPUT}") + set(TARGET_INPUT "${CMAKE_CURRENT_SOURCE_DIR}/${TARGET_INPUT}") endif() + + get_target_property(CANONICAL_IDENTIFIERS ${IMPL_TARGET} NBL_CANONICAL_IDENTIFIERS) + + set(NEW_CANONICAL_IDENTIFIER "${IMPL_BINARY_DIR}/${BASE_KEY}") + if(CANONICAL_IDENTIFIERS) + list(FIND CANONICAL_IDENTIFIERS "${NEW_CANONICAL_IDENTIFIER}" FOUND) + + if(NOT FOUND STREQUAL -1) + string(JSON ITEM GET "${IMPL_INPUTS}" ${INDEX}) + message(FATAL_ERROR "While parsing ${IMPL_TARGET}'s NSC compile rule\n${ITEM}\nwith binary directory \"${IMPL_BINARY_DIR}\",\ncanonical key \"${BASE_KEY}\" already defined!") + endif() + endif() + + set_property(TARGET ${IMPL_TARGET} APPEND PROPERTY NBL_CANONICAL_IDENTIFIERS "${NEW_CANONICAL_IDENTIFIER}") + + set(HEADER_ITEM_VIEW [=[ +namespace @IMPL_NAMESPACE@ { + template<> + inline const nbl::core::string get_spirv_key + (const nbl::video::SPhysicalDeviceLimits& limits, const nbl::video::SPhysicalDeviceFeatures& features) + { + nbl::core::string retval = "@BASE_KEY@"; +@RETVAL_EVAL@ + retval += ".spv"; + return retval; + } +} + +]=]) + unset(RETVAL_EVAL) + foreach(CAP ${CAP_NAMES}) + string(CONFIGURE [=[ + retval += ".@CAP@_" + std::to_string(limits.@CAP@); +]=] RETVALUE_VIEW @ONLY) + string(APPEND RETVAL_EVAL "${RETVALUE_VIEW}") + endforeach(CAP) + string(CONFIGURE "${HEADER_ITEM_VIEW}" HEADER_ITEM_EVAL @ONLY) + set_property(TARGET ${IMPL_TARGET} APPEND_STRING PROPERTY NBL_HEADER_CONTENT "${HEADER_ITEM_EVAL}") + + function(GENERATE_KEYS PREFIX CAP_INDEX CAPS_EVAL_PART) + if(NUM_CAPS EQUAL 0 OR CAP_INDEX EQUAL ${NUM_CAPS}) + set(FINAL_KEY "${BASE_KEY}${PREFIX}.spv") # always add ext even if its already there to make sure asset loader always is able to load as IShader + + set(TARGET_OUTPUT "${IMPL_BINARY_DIR}/${FINAL_KEY}") + set(CONFIG_FILE "${TARGET_OUTPUT}.config") + set(CAPS_EVAL "${CAPS_EVAL_PART}") + + string(CONFIGURE "${DEVICE_CONFIG_VIEW}" CONFIG_CONTENT @ONLY) + file(WRITE "${CONFIG_FILE}" "${CONFIG_CONTENT}") + + set(NBL_NSC_COMPILE_COMMAND + "$" + -Fc "${TARGET_OUTPUT}" + ${COMPILE_OPTIONS} ${REQUIRED_OPTIONS} ${IMPL_COMMON_OPTIONS} + "${CONFIG_FILE}" + ) + + add_custom_command(OUTPUT "${TARGET_OUTPUT}" + COMMAND ${NBL_NSC_COMPILE_COMMAND} + DEPENDS ${DEPENDS_ON} + COMMENT "Creating \"${TARGET_OUTPUT}\"" + VERBATIM + COMMAND_EXPAND_LISTS + ) + + set(HEADER_ONLY_LIKE "${CONFIG_FILE}" "${TARGET_INPUT}" "${TARGET_OUTPUT}") + target_sources(${IMPL_TARGET} PRIVATE ${HEADER_ONLY_LIKE}) + + set_source_files_properties(${HEADER_ONLY_LIKE} PROPERTIES + HEADER_FILE_ONLY ON + VS_TOOL_OVERRIDE None + ) + + set_source_files_properties("${TARGET_OUTPUT}" PROPERTIES + NBL_SPIRV_REGISTERED_INPUT "${TARGET_INPUT}" + NBL_SPIRV_PERMUTATION_CONFIG "${CONFIG_FILE}" + NBL_SPIRV_BINARY_DIR "${IMPL_BINARY_DIR}" + NBL_SPIRV_ACCESS_KEY "${FINAL_KEY}" + ) + + set_property(TARGET ${IMPL_TARGET} APPEND PROPERTY NBL_SPIRV_OUTPUTS "${TARGET_OUTPUT}") + return() + endif() + + list(GET CAP_NAMES ${CAP_INDEX} CURRENT_CAP) + list(GET CAP_TYPES ${CAP_INDEX} CURRENT_TYPE) + set(VAR_NAME "CAP_VALUES_${CAP_INDEX}") + set(VALUES "${${VAR_NAME}}") + + foreach(V IN LISTS VALUES) + set(NEW_PREFIX "${PREFIX}.${CURRENT_CAP}_${V}") + set(NEW_EVAL "${CAPS_EVAL_PART}NBL_CONSTEXPR_STATIC_INLINE ${CURRENT_TYPE} ${CURRENT_CAP} = (${CURRENT_TYPE}) ${V}; // got permuted\n") + math(EXPR NEXT_INDEX "${CAP_INDEX} + 1") + GENERATE_KEYS("${NEW_PREFIX}" "${NEXT_INDEX}" "${NEW_EVAL}") + endforeach() + endfunction() + + GENERATE_KEYS("" 0 "") + endforeach() + + unset(KEYS) + get_target_property(SPIRVs ${IMPL_TARGET} NBL_SPIRV_OUTPUTS) + foreach(SPIRV ${SPIRVs}) + get_source_file_property(CONFIG ${SPIRV} NBL_SPIRV_PERMUTATION_CONFIG) + get_source_file_property(INPUT ${SPIRV} NBL_SPIRV_REGISTERED_INPUT) + get_source_file_property(ACCESS_KEY ${SPIRV} NBL_SPIRV_ACCESS_KEY) + + list(APPEND CONFIGS ${CONFIG}) + list(APPEND INPUTS ${INPUT}) + list(APPEND KEYS ${ACCESS_KEY}) endforeach() + + set(RTE "NSC Rules") + set(IN "${RTE}/In") + set(OUT "${RTE}/Out") + + source_group("${IN}" FILES ${CONFIGS} ${INPUTS}) + source_group("${OUT}" FILES ${SPIRVs}) + + set(${IMPL_OUTPUT_VAR} ${KEYS} PARENT_SCOPE) +endfunction() + +function(NBL_CREATE_RESOURCE_ARCHIVE) + set(REQUIRED_SINGLE_ARGS TARGET BIND NAMESPACE MOUNT_POINT_DEFINE) + cmake_parse_arguments(IMPL "" "${REQUIRED_SINGLE_ARGS}" "BUILTINS" ${ARGV}) + NBL_PARSE_REQUIRED(IMPL ${REQUIRED_SINGLE_ARGS}) + + set(IMPL_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${IMPL_TARGET}") + + set(_BUNDLE_ARCHIVE_ABSOLUTE_PATH_ "") + get_filename_component(_BUNDLE_SEARCH_DIRECTORY_ "${IMPL_BIND}" ABSOLUTE) + get_filename_component(_OUTPUT_DIRECTORY_SOURCE_ "${IMPL_OUTPUT_DIRECTORY}/archive/src" ABSOLUTE) + get_filename_component(_OUTPUT_DIRECTORY_HEADER_ "${IMPL_OUTPUT_DIRECTORY}/archive/include" ABSOLUTE) + + set(_BUILTIN_RESOURCES_NAMESPACE_ ${IMPL_NAMESPACE}) + set(_LINK_MODE_ STATIC) + + get_filename_component(BUILTIN_ARCHIVE_INPUT_ABS_ENTRY "${IMPL_INPUT_DIRECTORY}" ABSOLUTE) + set(BUILTIN_KEY_ENTRY_ABS "${BUILTIN_ARCHIVE_INPUT_ABS_ENTRY}/${_BUNDLE_ARCHIVE_ABSOLUTE_PATH_}") + + if(NBL_EMBED_BUILTIN_RESOURCES) + foreach(IT ${IMPL_BUILTINS}) + if(NBL_LOG_VERBOSE) + message(STATUS "[${IMPL_TARGET}'s Builtins]: Registered \"${IT}\" key") + endif() + + LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED ${IT}) + endforeach() + + ADD_CUSTOM_BUILTIN_RESOURCES(${IMPL_TARGET} NBL_RESOURCES_TO_EMBED "${_BUNDLE_SEARCH_DIRECTORY_}" "${_BUNDLE_ARCHIVE_ABSOLUTE_PATH_}" "${_BUILTIN_RESOURCES_NAMESPACE_}" "${_OUTPUT_DIRECTORY_HEADER_}" "${_OUTPUT_DIRECTORY_SOURCE_}" "${_LINK_MODE_}") + else() + add_library(${IMPL_TARGET} INTERFACE) # (***) + endif() + + # TODO (***): actually I better have this in meta target created by NBL_CREATE_NSC_COMPILE_RULES, then I kill its INTERFACE when builtins are off + target_compile_definitions(${IMPL_TARGET} INTERFACE ${IMPL_MOUNT_POINT_DEFINE}="${_BUNDLE_SEARCH_DIRECTORY_}") endfunction() \ No newline at end of file diff --git a/docker/compiler-explorer b/docker/compiler-explorer index 45866dfa87..5437a9193b 160000 --- a/docker/compiler-explorer +++ b/docker/compiler-explorer @@ -1 +1 @@ -Subproject commit 45866dfa8782404fc121f25ce15ad0626b474db0 +Subproject commit 5437a9193b3765ba7b0a08894cdfcef5162e57bf diff --git a/examples_tests b/examples_tests index 66e486ca1a..a6271a4ca0 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 66e486ca1a33932c498d849effe9af3358ac1095 +Subproject commit a6271a4ca05eb0fe8bb7316f5bd857e64fdc3734 diff --git a/include/nbl/asset/IShader.h b/include/nbl/asset/IShader.h index 96ff73f3f0..d553dddf62 100644 --- a/include/nbl/asset/IShader.h +++ b/include/nbl/asset/IShader.h @@ -4,7 +4,8 @@ #ifndef _NBL_ASSET_I_SHADER_H_INCLUDED_ #define _NBL_ASSET_I_SHADER_H_INCLUDED_ - +#include "nbl/asset/IAsset.h" +#include "nbl/asset/ICPUBuffer.h" #include "nbl/core/declarations.h" #include "nbl/builtin/hlsl/enums.hlsl" diff --git a/include/nbl/asset/utils/IShaderCompiler.h b/include/nbl/asset/utils/IShaderCompiler.h index d4b8e50119..30d37f36c7 100644 --- a/include/nbl/asset/utils/IShaderCompiler.h +++ b/include/nbl/asset/utils/IShaderCompiler.h @@ -118,6 +118,17 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted std::string_view definition; }; + // + using E_SPIRV_VERSION = nbl::hlsl::SpirvVersion; + + static inline constexpr uint32_t getSpirvMajor(E_SPIRV_VERSION version) { + return (version >> 16u) & 0xFFu; + } + + static inline constexpr uint32_t getSpirvMinor(E_SPIRV_VERSION version) { + return (version >> 8u) & 0xFFu; + } + // struct SPreprocessorOptions { @@ -125,11 +136,9 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted system::logger_opt_ptr logger = nullptr; const CIncludeFinder* includeFinder = nullptr; std::span extraDefines = {}; + E_SPIRV_VERSION targetSpirvVersion = E_SPIRV_VERSION::ESV_1_6; }; - // - using E_SPIRV_VERSION = nbl::hlsl::SpirvVersion; - // https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#debugging enum class E_DEBUG_INFO_FLAGS : uint8_t { @@ -169,7 +178,6 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted virtual IShader::E_CONTENT_TYPE getCodeContentType() const { return IShader::E_CONTENT_TYPE::ECT_UNKNOWN; }; IShader::E_SHADER_STAGE stage = IShader::E_SHADER_STAGE::ESS_ALL_OR_LIBRARY; - E_SPIRV_VERSION targetSpirvVersion = E_SPIRV_VERSION::ESV_1_6; const ISPIRVOptimizer* spirvOptimizer = nullptr; core::bitflag debugInfoFlags = core::bitflag(E_DEBUG_INFO_FLAGS::EDIF_SOURCE_BIT) | E_DEBUG_INFO_FLAGS::EDIF_TOOL_BIT; SPreprocessorOptions preprocessorOptions = {}; @@ -301,7 +309,7 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted // Only SEntry should instantiate this struct SCompilerArgs(const SCompilerOptions& options) - : stage(options.stage), targetSpirvVersion(options.targetSpirvVersion), debugInfoFlags(options.debugInfoFlags), preprocessorArgs(options.preprocessorOptions) + : stage(options.stage), targetSpirvVersion(options.preprocessorOptions.targetSpirvVersion), debugInfoFlags(options.debugInfoFlags), preprocessorArgs(options.preprocessorOptions) { if (options.spirvOptimizer) { for (auto pass : options.spirvOptimizer->getPasses()) diff --git a/src/nbl/CMakeLists.txt b/src/nbl/CMakeLists.txt index cd9572daa5..15c8237585 100755 --- a/src/nbl/CMakeLists.txt +++ b/src/nbl/CMakeLists.txt @@ -118,178 +118,179 @@ unset(NABLA_HEADERS_PUBLIC2 ${NBL_TMP_FULL_PATHS}) # set(NBL_CORE_SOURCES - ${NBL_ROOT_PATH}/src/nbl/core/IReferenceCounted.cpp - ${NBL_ROOT_PATH}/src/nbl/core/alloc/refctd_memory_resource.cpp - ${NBL_ROOT_PATH}/src/nbl/core/hash/blake.cpp + core/IReferenceCounted.cpp + core/alloc/refctd_memory_resource.cpp + core/hash/blake.cpp ) set(NBL_SYSTEM_SOURCES - ${NBL_ROOT_PATH}/src/nbl/system/DefaultFuncPtrLoader.cpp - ${NBL_ROOT_PATH}/src/nbl/system/IFileBase.cpp - ${NBL_ROOT_PATH}/src/nbl/system/ILogger.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CArchiveLoaderZip.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CArchiveLoaderTar.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CAPKResourcesArchive.cpp - ${NBL_ROOT_PATH}/src/nbl/system/ISystem.cpp - ${NBL_ROOT_PATH}/src/nbl/system/IFileArchive.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CColoredStdoutLoggerWin32.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CStdoutLoggerAndroid.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CFileViewVirtualAllocatorWin32.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CFileViewVirtualAllocatorPOSIX.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CFileViewAPKAllocator.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CFileWin32.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CFilePOSIX.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CSystemWin32.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CSystemAndroid.cpp - ${NBL_ROOT_PATH}/src/nbl/system/ISystemPOSIX.cpp - ${NBL_ROOT_PATH}/src/nbl/system/CSystemLinux.cpp + system/DefaultFuncPtrLoader.cpp + system/IFileBase.cpp + system/ILogger.cpp + system/CArchiveLoaderZip.cpp + system/CArchiveLoaderTar.cpp + system/CAPKResourcesArchive.cpp + system/ISystem.cpp + system/IFileArchive.cpp + system/CColoredStdoutLoggerWin32.cpp + system/CStdoutLoggerAndroid.cpp + system/CFileViewVirtualAllocatorWin32.cpp + system/CFileViewVirtualAllocatorPOSIX.cpp + system/CFileViewAPKAllocator.cpp + system/CFileWin32.cpp + system/CFilePOSIX.cpp + system/CSystemWin32.cpp + system/CSystemAndroid.cpp + system/ISystemPOSIX.cpp + system/CSystemLinux.cpp ) set(NBL_UI_SOURCES - ${NBL_ROOT_PATH}/src/nbl/ui/CWindowWin32.cpp - ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerWin32.cpp - ${NBL_ROOT_PATH}/src/nbl/ui/CWindowManagerAndroid.cpp - ${NBL_ROOT_PATH}/src/nbl/ui/CGraphicalApplicationAndroid.cpp + ui/CWindowWin32.cpp + ui/CWindowManagerWin32.cpp + ui/CWindowManagerAndroid.cpp + ui/CGraphicalApplicationAndroid.cpp ) set(NBL_ASSET_SOURCES # Assets - ${NBL_ROOT_PATH}/src/nbl/asset/IAsset.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/IRenderpass.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/IAssetManager.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/ICPUDescriptorSet.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/ICPUImage.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/ICPUPolygonGeometry.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/IAssetWriter.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/IAssetLoader.cpp + asset/IAsset.cpp + asset/IRenderpass.cpp + asset/IAssetManager.cpp + asset/ICPUDescriptorSet.cpp + asset/ICPUImage.cpp + asset/ICPUPolygonGeometry.cpp + asset/interchange/IAssetWriter.cpp + asset/interchange/IAssetLoader.cpp # Shaders - ${NBL_ROOT_PATH}/src/nbl/asset/utils/ISPIRVOptimizer.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/ISPIRVEntryPointTrimmer.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/IShaderCompiler.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/CGLSLCompiler.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/CHLSLCompiler.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/CCompilerSet.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/CSPIRVIntrospector.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CGLSLLoader.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CHLSLLoader.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CSPVLoader.cpp + asset/utils/ISPIRVOptimizer.cpp + asset/utils/ISPIRVEntryPointTrimmer.cpp + asset/utils/IShaderCompiler.cpp + asset/utils/CGLSLCompiler.cpp + asset/utils/CHLSLCompiler.cpp + asset/utils/CWaveStringResolver.cpp + asset/utils/CCompilerSet.cpp + asset/utils/CSPIRVIntrospector.cpp + asset/interchange/CGLSLLoader.cpp + asset/interchange/CHLSLLoader.cpp + asset/interchange/CSPVLoader.cpp # Pipeline loaders - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CGraphicsPipelineLoaderMTL.cpp + asset/interchange/CGraphicsPipelineLoaderMTL.cpp # Meshes - ${NBL_ROOT_PATH}/src/nbl/asset/utils/CForsythVertexCacheOptimizer.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/CSmoothNormalGenerator.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/CGeometryCreator.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/CPolygonGeometryManipulator.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/COverdrawPolygonGeometryOptimizer.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/CSmoothNormalGenerator.cpp + asset/utils/CForsythVertexCacheOptimizer.cpp + asset/utils/CSmoothNormalGenerator.cpp + asset/utils/CGeometryCreator.cpp + asset/utils/CPolygonGeometryManipulator.cpp + asset/utils/COverdrawPolygonGeometryOptimizer.cpp + asset/utils/CSmoothNormalGenerator.cpp # Mesh loaders - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/COBJMeshFileLoader.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CPLYMeshFileLoader.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CSTLMeshFileLoader.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CBufferLoaderBIN.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CGLTFLoader.cpp + asset/interchange/COBJMeshFileLoader.cpp + asset/interchange/CPLYMeshFileLoader.cpp + asset/interchange/CSTLMeshFileLoader.cpp + asset/interchange/CBufferLoaderBIN.cpp + asset/interchange/CGLTFLoader.cpp # Mesh writers - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CPLYMeshWriter.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CSTLMeshWriter.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CGLTFWriter.cpp + asset/interchange/CPLYMeshWriter.cpp + asset/interchange/CSTLMeshWriter.cpp + asset/interchange/CGLTFWriter.cpp # Images - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/IImageAssetHandlerBase.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/filters/CBasicImageFilterCommon.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/filters/kernels/CConvolutionWeightFunction.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/utils/CDerivativeMapCreator.cpp + asset/interchange/IImageAssetHandlerBase.cpp + asset/filters/CBasicImageFilterCommon.cpp + asset/filters/kernels/CConvolutionWeightFunction.cpp + asset/utils/CDerivativeMapCreator.cpp # Image loaders - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/IImageLoader.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CImageLoaderJPG.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CImageLoaderPNG.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CImageLoaderTGA.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CImageLoaderOpenEXR.cpp # TODO: Nahim - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CGLILoader.cpp + asset/interchange/IImageLoader.cpp + asset/interchange/CImageLoaderJPG.cpp + asset/interchange/CImageLoaderPNG.cpp + asset/interchange/CImageLoaderTGA.cpp + asset/interchange/CImageLoaderOpenEXR.cpp # TODO: Nahim + asset/interchange/CGLILoader.cpp # Image writers - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/IImageWriter.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CImageWriterJPG.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CImageWriterPNG.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CImageWriterTGA.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CImageWriterOpenEXR.cpp # TODO: Nahim - ${NBL_ROOT_PATH}/src/nbl/asset/interchange/CGLIWriter.cpp + asset/interchange/IImageWriter.cpp + asset/interchange/CImageWriterJPG.cpp + asset/interchange/CImageWriterPNG.cpp + asset/interchange/CImageWriterTGA.cpp + asset/interchange/CImageWriterOpenEXR.cpp # TODO: Nahim + asset/interchange/CGLIWriter.cpp # Material compiler - ${NBL_ROOT_PATH}/src/nbl/asset/material_compiler/CMaterialCompilerGLSLBackendCommon.cpp - ${NBL_ROOT_PATH}/src/nbl/asset/material_compiler/CMaterialCompilerGLSLRasterBackend.cpp + asset/material_compiler/CMaterialCompilerGLSLBackendCommon.cpp + asset/material_compiler/CMaterialCompilerGLSLRasterBackend.cpp ) set(NBL_VIDEO_SOURCES # Utilities - ${NBL_ROOT_PATH}/src/nbl/video/utilities/ImageRegionIterator.cpp - ${NBL_ROOT_PATH}/src/nbl/video/utilities/ICommandPoolCache.cpp - ${NBL_ROOT_PATH}/src/nbl/video/utilities/IPropertyPool.cpp - ${NBL_ROOT_PATH}/src/nbl/video/utilities/IUtilities.cpp - ${NBL_ROOT_PATH}/src/nbl/video/utilities/CPropertyPoolHandler.cpp - ${NBL_ROOT_PATH}/src/nbl/video/utilities/CScanner.cpp - ${NBL_ROOT_PATH}/src/nbl/video/utilities/CComputeBlit.cpp - ${NBL_ROOT_PATH}/src/nbl/video/utilities/CAssetConverter.cpp + video/utilities/ImageRegionIterator.cpp + video/utilities/ICommandPoolCache.cpp + video/utilities/IPropertyPool.cpp + video/utilities/IUtilities.cpp + video/utilities/CPropertyPoolHandler.cpp + video/utilities/CScanner.cpp + video/utilities/CComputeBlit.cpp + video/utilities/CAssetConverter.cpp # Interfaces - ${NBL_ROOT_PATH}/src/nbl/video/IAPIConnection.cpp - ${NBL_ROOT_PATH}/src/nbl/video/IPhysicalDevice.cpp - ${NBL_ROOT_PATH}/src/nbl/video/IDescriptorPool.cpp - ${NBL_ROOT_PATH}/src/nbl/video/ILogicalDevice.cpp - ${NBL_ROOT_PATH}/src/nbl/video/IGPUAccelerationStructure.cpp - ${NBL_ROOT_PATH}/src/nbl/video/IGPUCommandBuffer.cpp - ${NBL_ROOT_PATH}/src/nbl/video/IQueue.cpp - ${NBL_ROOT_PATH}/src/nbl/video/IGPUDescriptorSet.cpp - ${NBL_ROOT_PATH}/src/nbl/video/IDeviceMemoryAllocation.cpp - ${NBL_ROOT_PATH}/src/nbl/video/IDeviceMemoryBacked.cpp - ${NBL_ROOT_PATH}/src/nbl/video/ISemaphore.cpp - ${NBL_ROOT_PATH}/src/nbl/video/ISwapchain.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CJITIncludeLoader.cpp + video/IAPIConnection.cpp + video/IPhysicalDevice.cpp + video/IDescriptorPool.cpp + video/ILogicalDevice.cpp + video/IGPUAccelerationStructure.cpp + video/IGPUCommandBuffer.cpp + video/IQueue.cpp + video/IGPUDescriptorSet.cpp + video/IDeviceMemoryAllocation.cpp + video/IDeviceMemoryBacked.cpp + video/ISemaphore.cpp + video/ISwapchain.cpp + video/CJITIncludeLoader.cpp # Vulkan - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanDeviceMemoryBacked.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanSwapchain.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanImage.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanQueue.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanSemaphore.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanFramebuffer.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanRenderpass.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanImageView.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanCommandBuffer.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanCommandPool.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanBuffer.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanDescriptorSetLayout.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanPipelineLayout.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanPipelineCache.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanComputePipeline.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanDescriptorPool.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanDescriptorSet.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanMemoryAllocation.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanBufferView.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanLogicalDevice.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanDeferredOperation.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanAccelerationStructure.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanQueryPool.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanSampler.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanConnection.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanPhysicalDevice.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanGraphicsPipeline.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanRayTracingPipeline.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CVulkanEvent.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CSurfaceVulkan.cpp + video/CVulkanDeviceMemoryBacked.cpp + video/CVulkanSwapchain.cpp + video/CVulkanImage.cpp + video/CVulkanQueue.cpp + video/CVulkanSemaphore.cpp + video/CVulkanFramebuffer.cpp + video/CVulkanRenderpass.cpp + video/CVulkanImageView.cpp + video/CVulkanCommandBuffer.cpp + video/CVulkanCommandPool.cpp + video/CVulkanBuffer.cpp + video/CVulkanDescriptorSetLayout.cpp + video/CVulkanPipelineLayout.cpp + video/CVulkanPipelineCache.cpp + video/CVulkanComputePipeline.cpp + video/CVulkanDescriptorPool.cpp + video/CVulkanDescriptorSet.cpp + video/CVulkanMemoryAllocation.cpp + video/CVulkanBufferView.cpp + video/CVulkanLogicalDevice.cpp + video/CVulkanDeferredOperation.cpp + video/CVulkanAccelerationStructure.cpp + video/CVulkanQueryPool.cpp + video/CVulkanSampler.cpp + video/CVulkanConnection.cpp + video/CVulkanPhysicalDevice.cpp + video/CVulkanGraphicsPipeline.cpp + video/CVulkanRayTracingPipeline.cpp + video/CVulkanEvent.cpp + video/CSurfaceVulkan.cpp # CUDA - ${NBL_ROOT_PATH}/src/nbl/video/CCUDAHandler.cpp - ${NBL_ROOT_PATH}/src/nbl/video/CCUDADevice.cpp + video/CCUDAHandler.cpp + video/CCUDADevice.cpp ) set(NBL_SCENE_SOURCES - ${NBL_ROOT_PATH}/src/nbl/scene/ITransformTree.cpp + scene/ITransformTree.cpp ) set(NBL_META_SOURCES - ${NBL_ROOT_PATH}/src/nbl/gtml.cpp + gtml.cpp ) set(NABLA_SRCS_COMMON @@ -342,6 +343,16 @@ endif() nbl_adjust_flags(TARGET Nabla MAP_RELEASE Release MAP_RELWITHDEBINFO RelWithDebInfo MAP_DEBUG Debug) nbl_adjust_definitions() +option(NBL_WAVE_STRING_RESOLVER_TU_DEBUG_OPTIMISATION "Enable to optimise CWaveStringResolver.cpp in Debug configuration, uses RWDI compile options for the TU" ON) +if(NBL_WAVE_STRING_RESOLVER_TU_DEBUG_OPTIMISATION) + set_source_files_properties(asset/utils/CWaveStringResolver.cpp PROPERTIES + # just enabling inlining and optimisations will help a lot + COMPILE_OPTIONS "$<$:${NBL_CXX_RELWITHDEBINFO_COMPILE_OPTIONS}>" + # trade is you cannot mix with PCH + set this property per config (it seems), different compile options would lead to corrruptions and undefined behaviours + SKIP_PRECOMPILE_HEADERS ON + ) +endif() + if(NBL_EXPLICIT_MODULE_LOAD_LOG) target_compile_definitions(Nabla PUBLIC NBL_EXPLICIT_MODULE_LOAD_LOG) endif() diff --git a/src/nbl/asset/utils/CGLSLCompiler.cpp b/src/nbl/asset/utils/CGLSLCompiler.cpp index 723bad2a7b..a593a11597 100644 --- a/src/nbl/asset/utils/CGLSLCompiler.cpp +++ b/src/nbl/asset/utils/CGLSLCompiler.cpp @@ -266,7 +266,7 @@ core::smart_refctd_ptr CGLSLCompiler::compileToSPIRV_impl(const std::st shaderc::Compiler comp; shaderc::CompileOptions shadercOptions; //default options - shadercOptions.SetTargetSpirv(static_cast(glslOptions.targetSpirvVersion)); + shadercOptions.SetTargetSpirv(static_cast(glslOptions.preprocessorOptions.targetSpirvVersion)); const shaderc_shader_kind stage = glslOptions.stage == IShader::E_SHADER_STAGE::ESS_UNKNOWN ? shaderc_glsl_infer_from_source : ESStoShadercEnum(glslOptions.stage); if (glslOptions.debugInfoFlags.value != IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_NONE) shadercOptions.SetGenerateDebugInfo(); diff --git a/src/nbl/asset/utils/CHLSLCompiler.cpp b/src/nbl/asset/utils/CHLSLCompiler.cpp index f99d81d01f..4420a4d319 100644 --- a/src/nbl/asset/utils/CHLSLCompiler.cpp +++ b/src/nbl/asset/utils/CHLSLCompiler.cpp @@ -342,9 +342,12 @@ static DxcCompilationResult dxcCompile(const CHLSLCompiler* compiler, nbl::asset return result; } - #include "nbl/asset/utils/waveContext.h" +namespace nbl::wave +{ + extern nbl::core::string preprocess(std::string& code, const IShaderCompiler::SPreprocessorOptions& preprocessOptions, bool withCaching, std::function post); +} std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADER_STAGE& stage, const SPreprocessorOptions& preprocessOptions, std::vector& dxc_compile_flags_override, std::vector* dependencies) const { @@ -361,37 +364,22 @@ std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADE } } - nbl::wave::context context(code.begin(),code.end(),preprocessOptions.sourceIdentifier.data(),{preprocessOptions}); - // If dependencies were passed, we assume we want caching - context.set_caching(bool(dependencies)); - context.add_macro_definition("__HLSL_VERSION"); - - // instead of defining extraDefines as "NBL_GLSL_LIMIT_MAX_IMAGE_DIMENSION_1D 32768", - // now define them as "NBL_GLSL_LIMIT_MAX_IMAGE_DIMENSION_1D=32768" - // to match boost wave syntax - // https://www.boost.org/doc/libs/1_82_0/libs/wave/doc/class_reference_context.html#:~:text=Maintain%20defined%20macros-,add_macro_definition,-bool%20add_macro_definition - for (const auto& define : preprocessOptions.extraDefines) - context.add_macro_definition(define.identifier.data()+core::string("=")+define.definition.data()); - // preprocess - core::string resolvedString; - try - { - std::stringstream stream = std::stringstream(); - for (auto i=context.begin(); i!=context.end(); i++) - stream << i->get_value(); - resolvedString = stream.str(); - } - catch (boost::wave::preprocess_exception& e) - { - preprocessOptions.logger.log("%s exception caught. %s [%s:%d:%d]",system::ILogger::ELL_ERROR,e.what(),e.description(),e.file_name(),e.line_no(),e.column_no()); - return {}; - } - catch (...) - { - preprocessOptions.logger.log("Unknown exception caught!",system::ILogger::ELL_ERROR); - return {}; - } + core::string resolvedString = nbl::wave::preprocess(code, preprocessOptions, bool(dependencies) /* if dependencies were passed, we assume we want caching*/, + [&dxc_compile_flags_override, &stage, &dependencies](nbl::wave::context& context) -> void + { + if (context.get_hooks().m_dxc_compile_flags_override.size() != 0) + dxc_compile_flags_override = context.get_hooks().m_dxc_compile_flags_override; + + // pragma overrides what we passed in + if (context.get_hooks().m_pragmaStage != IShader::E_SHADER_STAGE::ESS_UNKNOWN) + stage = context.get_hooks().m_pragmaStage; + + if (dependencies) { + *dependencies = std::move(context.get_dependencies()); + } + } + ); // for debugging cause MSVC doesn't like to show more than 21k LoC in TextVisualizer if constexpr (true) @@ -406,17 +394,6 @@ std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADE } } - if (context.get_hooks().m_dxc_compile_flags_override.size() != 0) - dxc_compile_flags_override = context.get_hooks().m_dxc_compile_flags_override; - - // pragma overrides what we passed in - if(context.get_hooks().m_pragmaStage != IShader::E_SHADER_STAGE::ESS_UNKNOWN) - stage = context.get_hooks().m_pragmaStage; - - if (dependencies) { - *dependencies = std::move(context.get_dependencies()); - } - return resolvedString; } @@ -437,6 +414,7 @@ core::smart_refctd_ptr CHLSLCompiler::compileToSPIRV_impl(const std::st } std::vector dxc_compile_flags = {}; IShader::E_SHADER_STAGE stage = options.stage; + auto newCode = preprocessShader(std::string(code), stage, hlslOptions.preprocessorOptions, dxc_compile_flags, dependencies); if (newCode.empty()) return nullptr; @@ -457,7 +435,7 @@ core::smart_refctd_ptr CHLSLCompiler::compileToSPIRV_impl(const std::st for (size_t i = 0; i < required.size(); i++) arguments.push_back(required[i]); // - switch (options.targetSpirvVersion) + switch (options.preprocessorOptions.targetSpirvVersion) { case hlsl::SpirvVersion::ESV_1_4: arguments.push_back(L"-fspv-target-env=vulkan1.1spirv1.4"); diff --git a/src/nbl/asset/utils/CWaveStringResolver.cpp b/src/nbl/asset/utils/CWaveStringResolver.cpp new file mode 100644 index 0000000000..77207f84ca --- /dev/null +++ b/src/nbl/asset/utils/CWaveStringResolver.cpp @@ -0,0 +1,88 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h + +//! wave token preprocessing with isolated translation unit optimization +/* + the source has separate optimization flags because of how boost spirit (header only dep) the wave relies on is slow in Debug builds, ABI related + options remain and there is no mismatch, we force agressive inlining and optimizations mostly regardless build configuration by default +*/ + +/* + Arek leaving thoughts, TODO: + + in NBL_WAVE_STRING_RESOLVER_TU_DEBUG_OPTIMISATION mode enabled -> here in this TU do + + #define _ITERATOR_DEBUG_LEVEL 0 + #define _HAS_ITERATOR_DEBUGGING 0 + + and allow Nabla to mismatch debug iterator *on purpose* by + + #define _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH + + in Debug/RWDI + + then make preprocess full C API with raw in/out pointers and bytes out pointer, + with mismtach we must be very careful about memory ownership as STL stuff will have + different struct layouts and its easy to make a crash, we will have extra memcpy and + deallocation but as a trade each config will have almost the same preprocessing perf + which matters for our NSC integration + + then we can think to make use of existing shader cache and maybe consider HLSL PCH + which NSC would inject into each input + + NOTE: this approach allows to do all in single Nabla module, no extra proxy/fake shared DLL needed! + NOTE: yep I know I have currently a callback for which context size will differ accross TUs afterwards but will think about it + + or ignore it and take care of NSC special target creating global HLSL PCH injected into each registered input +*/ + +#include "nbl/asset/utils/IShaderCompiler.h" + +using namespace nbl; +using namespace nbl::asset; + +#include "nbl/asset/utils/waveContext.h" + +namespace nbl::wave +{ + std::string preprocess(std::string& code, const nbl::asset::IShaderCompiler::SPreprocessorOptions& preprocessOptions, bool withCaching, std::function post) + { + nbl::wave::context context(code.begin(), code.end(), preprocessOptions.sourceIdentifier.data(), { preprocessOptions }); + context.set_caching(withCaching); + context.add_macro_definition("__HLSL_VERSION"); + context.add_macro_definition("__SPIRV_MAJOR_VERSION__=" + std::to_string(IShaderCompiler::getSpirvMajor(preprocessOptions.targetSpirvVersion))); + context.add_macro_definition("__SPIRV_MINOR_VERSION__=" + std::to_string(IShaderCompiler::getSpirvMinor(preprocessOptions.targetSpirvVersion))); + + // instead of defining extraDefines as "NBL_GLSL_LIMIT_MAX_IMAGE_DIMENSION_1D 32768", + // now define them as "NBL_GLSL_LIMIT_MAX_IMAGE_DIMENSION_1D=32768" + // to match boost wave syntax + // https://www.boost.org/doc/libs/1_82_0/libs/wave/doc/class_reference_context.html#:~:text=Maintain%20defined%20macros-,add_macro_definition,-bool%20add_macro_definition + for (const auto& define : preprocessOptions.extraDefines) + context.add_macro_definition(define.identifier.data() + core::string("=") + define.definition.data()); + + // preprocess + core::string resolvedString; + try + { + auto stream = std::stringstream(); + for (auto i= context.begin(); i!= context.end(); i++) + stream << i->get_value(); + resolvedString = stream.str(); + } + catch (boost::wave::preprocess_exception& e) + { + preprocessOptions.logger.log("%s exception caught. %s [%s:%d:%d]",system::ILogger::ELL_ERROR,e.what(),e.description(),e.file_name(),e.line_no(),e.column_no()); + return {}; + } + catch (...) + { + preprocessOptions.logger.log("Unknown exception caught!",system::ILogger::ELL_ERROR); + return {}; + } + + post(context); + + return resolvedString; + } +} \ No newline at end of file diff --git a/src/nbl/asset/utils/waveContext.h b/src/nbl/asset/utils/waveContext.h index a374391576..f6c0014e39 100644 --- a/src/nbl/asset/utils/waveContext.h +++ b/src/nbl/asset/utils/waveContext.h @@ -5,17 +5,11 @@ #define _NBL_ASSET_WAVE_CONTEXT_H_INCLUDED_ //! This file is not supposed to be included in user-accesible header files -#define BOOST_WAVE_ENABLE_COMMANDLINE_MACROS 1 -#define BOOST_WAVE_SUPPORT_PRAGMA_ONCE 0 -#define BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES 1 -#define BOOST_WAVE_SERIALIZATION 0 -#define BOOST_WAVE_SUPPORT_INCLUDE_NEXT 0 #include #include #include -#include "nbl/core/declarations.h" - +#include "nbl/asset/utils/IShaderCompiler.h" namespace nbl::wave { @@ -48,8 +42,8 @@ struct load_to_string final struct preprocessing_hooks final : public boost::wave::context_policies::default_preprocessing_hooks { - preprocessing_hooks(const IShaderCompiler::SPreprocessorOptions& _preprocessOptions) - : m_includeFinder(_preprocessOptions.includeFinder), m_logger(_preprocessOptions.logger), m_pragmaStage(IShader::E_SHADER_STAGE::ESS_UNKNOWN), m_dxc_compile_flags_override() + preprocessing_hooks(const nbl::asset::IShaderCompiler::SPreprocessorOptions& _preprocessOptions) + : m_includeFinder(_preprocessOptions.includeFinder), m_logger(_preprocessOptions.logger), m_pragmaStage(nbl::asset::IShader::E_SHADER_STAGE::ESS_UNKNOWN), m_dxc_compile_flags_override() { hash_token_occurences = 0; } @@ -156,9 +150,9 @@ struct preprocessing_hooks final : public boost::wave::context_policies::default } - const IShaderCompiler::CIncludeFinder* m_includeFinder; + const asset::IShaderCompiler::CIncludeFinder* m_includeFinder; system::logger_opt_ptr m_logger; - IShader::E_SHADER_STAGE m_pragmaStage; + asset::IShader::E_SHADER_STAGE m_pragmaStage; int hash_token_occurences; std::vector m_dxc_compile_flags_override; diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index fcbe58eb41..9e4f35fc57 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -386,4 +386,4 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/tgmath/output_structs.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/prefix_sum_blur/blur.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/prefix_sum_blur/box_sampler.hlsl") -ADD_CUSTOM_BUILTIN_RESOURCES(nblBuiltinResourceData NBL_RESOURCES_TO_EMBED "${NBL_ROOT_PATH}/include" "nbl/builtin" "nbl::builtin" "${NBL_ROOT_PATH_BINARY}/include" "${NBL_ROOT_PATH_BINARY}/src" "STATIC" "INTERNAL") +ADD_CUSTOM_BUILTIN_RESOURCES(nblBuiltinResourceData NBL_RESOURCES_TO_EMBED "${NBL_ROOT_PATH}/include" "nbl/builtin" "nbl::builtin" "${NBL_ROOT_PATH_BINARY}/include" "${NBL_ROOT_PATH_BINARY}/src" "STATIC" "INTERNAL") \ No newline at end of file diff --git a/src/nbl/builtin/utils.cmake b/src/nbl/builtin/utils.cmake index 0653ff97a2..d791cd3aa4 100644 --- a/src/nbl/builtin/utils.cmake +++ b/src/nbl/builtin/utils.cmake @@ -247,4 +247,4 @@ function(ADD_CUSTOM_BUILTIN_RESOURCES _TARGET_NAME_ _BUNDLE_NAME_ _BUNDLE_SEARCH if(MSVC AND NBL_SANITIZE_ADDRESS) set_property(TARGET ${_TARGET_NAME_} PROPERTY COMPILE_OPTIONS /fsanitize=address) endif() -endfunction() +endfunction() \ No newline at end of file diff --git a/src/nbl/ext/CMakeLists.txt b/src/nbl/ext/CMakeLists.txt index 27f9464f3e..e0bcd223f6 100644 --- a/src/nbl/ext/CMakeLists.txt +++ b/src/nbl/ext/CMakeLists.txt @@ -54,4 +54,6 @@ if(NBL_BUILD_TEXT_RENDERING) add_subdirectory(TextRendering) endif() -propagate_changed_variables_to_parent_scope() \ No newline at end of file +propagate_changed_variables_to_parent_scope() + +NBL_ADJUST_FOLDERS(ext) \ No newline at end of file diff --git a/src/nbl/video/ILogicalDevice.cpp b/src/nbl/video/ILogicalDevice.cpp index 983daed190..a21e00e303 100644 --- a/src/nbl/video/ILogicalDevice.cpp +++ b/src/nbl/video/ILogicalDevice.cpp @@ -364,7 +364,7 @@ core::smart_refctd_ptr ILogicalDevice::compileShader(const SShad asset::IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_SOURCE_BIT | asset::IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_TOOL_BIT; commonCompileOptions.spirvOptimizer = creationParams.optimizer; - commonCompileOptions.targetSpirvVersion = m_physicalDevice->getLimits().spirvVersion; + commonCompileOptions.preprocessorOptions.targetSpirvVersion = m_physicalDevice->getLimits().spirvVersion; commonCompileOptions.readCache = creationParams.readCache; commonCompileOptions.writeCache = creationParams.writeCache; diff --git a/tools/nsc/main.cpp b/tools/nsc/main.cpp index f659b1adb4..c4ce43b326 100644 --- a/tools/nsc/main.cpp +++ b/tools/nsc/main.cpp @@ -225,12 +225,17 @@ class ShaderCompiler final : public system::IApplicationFramework m_logger->log("Error. Loaded shader file content is not HLSL.", ILogger::ELL_ERROR); return false; } + + auto start = std::chrono::high_resolution_clock::now(); auto compilation_result = compile_shader(shader.get(), shaderStage, file_to_compile); + auto end = std::chrono::high_resolution_clock::now(); // writie compiled shader to file as bytes if (compilation_result) { m_logger->log("Shader compilation successful.", ILogger::ELL_INFO); + const auto took = std::to_string(std::chrono::duration_cast(end - start).count()); + m_logger->log("Took %s ms.", ILogger::ELL_PERFORMANCE, took.c_str()); { const auto location = std::filesystem::path(output_filepath); const auto parentDirectory = location.parent_path();