diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 4ee86dcfcd..167419bb22 100755 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -543,9 +543,6 @@ nbl_install_dir(imath/src/Imath) nbl_install_file(blake/c/blake3.h) -nbl_install_file_spec(nlohmann_json/include/nlohmann/json_fwd.hpp nlohmann) -nbl_install_file_spec(nlohmann_json/include/nlohmann/detail/abi_macros.hpp nlohmann/detail) - nbl_install_dir(boost/superproject/libs/preprocessor/include/boost) nbl_install_file_spec(renderdoc/renderdoc_app.h renderdoc) diff --git a/3rdparty/Vulkan-Headers b/3rdparty/Vulkan-Headers index 33d7f51258..3dda5a1a87 160000 --- a/3rdparty/Vulkan-Headers +++ b/3rdparty/Vulkan-Headers @@ -1 +1 @@ -Subproject commit 33d7f512583b8de44d1b6384aa1cf482f92e53e9 +Subproject commit 3dda5a1a87b62fdf3baf4680edc41c00e85a7a22 diff --git a/3rdparty/Vulkan-Tools b/3rdparty/Vulkan-Tools index 761e7bf273..4b6f7101c1 160000 --- a/3rdparty/Vulkan-Tools +++ b/3rdparty/Vulkan-Tools @@ -1 +1 @@ -Subproject commit 761e7bf2736f3ad326fdfc1b3c1543f4e669fd5c +Subproject commit 4b6f7101c15e09a8931f2f81c97146d0dfe68bc5 diff --git a/CMakePresets.json b/CMakePresets.json index e91c46d8e9..269ecb6dcc 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -295,7 +295,32 @@ "CMAKE_BUILD_TYPE": "Debug", "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" } - } + }, + { + "name": "n4ce-configure-windows-msvc", + "hidden": false, + "binaryDir": "build/production/n4ce", + "cacheVariables": { + "NBL_STATIC_BUILD": "OFF", + "NBL_SKIP_BUILD_OPTIONS_VALIDATION": "ON", + "CMAKE_SUPPRESS_REGENERATION": "OFF", + "NBL_COMPILER_DYNAMIC_RUNTIME": "ON", + "NBL_EMBED_BUILTIN_RESOURCES": "ON", + "NBL_UPDATE_GIT_SUBMODULE": "OFF", + "NBL_COMPILE_WITH_CUDA": "OFF", + "NBL_BUILD_OPTIX": "OFF", + "NBL_BUILD_MITSUBA_LOADER": "OFF", + "NBL_BUILD_RADEON_RAYS": "OFF", + "_NBL_COMPILE_WITH_OPEN_EXR_": "ON", + "NBL_EXPLICIT_MODULE_LOAD_LOG": "ON", + "NBL_CPACK_NO_BUILD_DIRECTORY_MODULES": "ON", + "GIT_FAIL_IF_NONZERO_EXIT": "OFF" + }, + "displayName": "[N4CE]: Dynamic library target, Visual Studio 17 2022 generator, MSVC v143 toolset", + "description": "Configure as dynamic library with Visual Studio 17 2022 generator and MSVC v143 toolset", + "generator": "Visual Studio 17 2022", + "toolset": "v143" + } ], "buildPresets": [ { diff --git a/examples_tests b/examples_tests index 2b4db21239..8a29f18026 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 2b4db2123918f380cc0a35f6889315a02f84ea73 +Subproject commit 8a29f18026a277589d7b2b672ab13fc572f70448 diff --git a/include/nbl/application_templates/MonoDeviceApplication.hpp b/include/nbl/application_templates/MonoDeviceApplication.hpp index a3a169d7b7..c7a94fe332 100644 --- a/include/nbl/application_templates/MonoDeviceApplication.hpp +++ b/include/nbl/application_templates/MonoDeviceApplication.hpp @@ -24,7 +24,8 @@ class MonoDeviceApplication : public virtual MonoSystemMonoLoggerApplication virtual bool onAppTerminated() override { // break the circular references from queues tracking submit resources - m_device->waitIdle(); + if (m_device) + m_device->waitIdle(); m_device = nullptr; m_api = nullptr; return base_t::onAppTerminated(); diff --git a/include/nbl/asset/utils/IShaderCompiler.h b/include/nbl/asset/utils/IShaderCompiler.h index 30d37f36c7..2052174d92 100644 --- a/include/nbl/asset/utils/IShaderCompiler.h +++ b/include/nbl/asset/utils/IShaderCompiler.h @@ -12,9 +12,7 @@ #include "nbl/asset/IShader.h" #include "nbl/asset/utils/ISPIRVOptimizer.h" - -// Less leakage than "nlohmann/json.hpp" only forward declarations -#include "nlohmann/json_fwd.hpp" +#include "nbl/system/json.h" #include "nbl/builtin/hlsl/enums.hlsl" @@ -111,11 +109,10 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted // struct SMacroDefinition { - friend void to_json(nlohmann::json&, const SMacroDefinition&); - friend void from_json(const nlohmann::json&, SMacroDefinition&); - std::string_view identifier; std::string_view definition; + + friend struct system::json::adl_serializer; }; // @@ -216,9 +213,8 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted inline SPreprocessingDependency() {} private: - friend void to_json(nlohmann::json& j, const SEntry::SPreprocessingDependency& dependency); - friend void from_json(const nlohmann::json& j, SEntry::SPreprocessingDependency& dependency); friend class CCache; + friend struct system::json::adl_serializer; // path or identifier system::path requestingSourceDir = ""; @@ -252,8 +248,7 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted friend class SCompilerArgs; friend class SEntry; friend class CCache; - friend void to_json(nlohmann::json&, const SPreprocessorArgs&); - friend void from_json(const nlohmann::json&, SPreprocessorArgs&); + friend struct system::json::adl_serializer; // Default constructor needed for json serialization of SCompilerArgs SPreprocessorArgs() {}; @@ -295,8 +290,7 @@ class NBL_API2 IShaderCompiler : public core::IReferenceCounted private: friend class SEntry; friend class CCache; - friend void to_json(nlohmann::json&, const SCompilerArgs&); - friend void from_json(const nlohmann::json&, SCompilerArgs&); + friend struct system::json::adl_serializer; // Default constructor needed for json serialization of SEntry SCompilerArgs() {} diff --git a/include/nbl/builtin/hlsl/ieee754.hlsl b/include/nbl/builtin/hlsl/ieee754.hlsl index 307a11101f..ea6361719a 100644 --- a/include/nbl/builtin/hlsl/ieee754.hlsl +++ b/include/nbl/builtin/hlsl/ieee754.hlsl @@ -239,8 +239,8 @@ struct flipSignIfRHSNegative_helper -NBL_CONSTEXPR_INLINE_FUNC T flipSign(T val, U flip) +template +NBL_CONSTEXPR_INLINE_FUNC T flipSign(T val, U flip = true) { return impl::flipSign_helper::__call(val, flip); } diff --git a/include/nbl/system/json.h b/include/nbl/system/json.h new file mode 100644 index 0000000000..1fdd0abf47 --- /dev/null +++ b/include/nbl/system/json.h @@ -0,0 +1,15 @@ +#ifndef _NBL_SYSTEM_JSON_H_INCLUDED_ +#define _NBL_SYSTEM_JSON_H_INCLUDED_ + +namespace nbl::system::json { + template struct adl_serializer; +} + +#define NBL_JSON_IMPL_BIND_ADL_SERIALIZER(T) \ +namespace nlohmann { \ + template<> \ + struct adl_serializer \ + : T {}; \ +} + +#endif // _NBL_SYSTEM_JSON_H_INCLUDED_ \ No newline at end of file diff --git a/include/nbl/video/ILogicalDevice.h b/include/nbl/video/ILogicalDevice.h index 180342e2d4..a269be082e 100644 --- a/include/nbl/video/ILogicalDevice.h +++ b/include/nbl/video/ILogicalDevice.h @@ -831,6 +831,7 @@ class NBL_API2 ILogicalDevice : public core::IReferenceCounted, public IDeviceMe asset::IShaderCompiler::CCache* writeCache = nullptr; std::span extraDefines = {}; hlsl::ShaderStage stage = hlsl::ShaderStage::ESS_ALL_OR_LIBRARY; + core::bitflag debugInfoFlags = asset::IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_NONE; }; core::smart_refctd_ptr compileShader(const SShaderCreationParameters& creationParams); diff --git a/include/nbl/video/utilities/IUtilities.h b/include/nbl/video/utilities/IUtilities.h index 7817df8d23..f52d5d36ef 100644 --- a/include/nbl/video/utilities/IUtilities.h +++ b/include/nbl/video/utilities/IUtilities.h @@ -37,8 +37,10 @@ class NBL_API2 IUtilities : public core::IReferenceCounted , m_allocationAlignment(allocationAlignment) , m_allocationAlignmentForBufferImageCopy(allocationAlignmentForBufferImageCopy) { - m_defaultDownloadBuffer->getBuffer()->setObjectDebugName(("Default Download Buffer of Utilities "+std::to_string(ptrdiff_t(this))).c_str()); - m_defaultUploadBuffer->getBuffer()->setObjectDebugName(("Default Upload Buffer of Utilities "+std::to_string(ptrdiff_t(this))).c_str()); + if (m_defaultDownloadBuffer) + m_defaultDownloadBuffer->getBuffer()->setObjectDebugName(("Default Download Buffer of Utilities "+std::to_string(ptrdiff_t(this))).c_str()); + if (m_defaultUploadBuffer) + m_defaultUploadBuffer->getBuffer()->setObjectDebugName(("Default Upload Buffer of Utilities "+std::to_string(ptrdiff_t(this))).c_str()); } IUtilities() = delete; @@ -94,6 +96,7 @@ class NBL_API2 IUtilities : public core::IReferenceCounted core::smart_refctd_ptr > defaultDownloadBuffer = nullptr; // Try Create Download Buffer + if (downstreamSize > 0u) { IGPUBuffer::SCreationParams streamingBufferCreationParams = {}; streamingBufferCreationParams.size = downstreamSize; @@ -127,6 +130,7 @@ class NBL_API2 IUtilities : public core::IReferenceCounted defaultDownloadBuffer = core::make_smart_refctd_ptr>(asset::SBufferRange{0ull,downstreamSize,std::move(buffer)},maxStreamingBufferAllocationAlignment,minStreamingBufferAllocationSize); } // Try Create Upload Buffer + if (upstreamSize > 0u) { IGPUBuffer::SCreationParams streamingBufferCreationParams = {}; streamingBufferCreationParams.size = upstreamSize; @@ -374,6 +378,11 @@ class NBL_API2 IUtilities : public core::IReferenceCounted //! * data must not be nullptr inline bool updateBufferRangeViaStagingBuffer(SIntendedSubmitInfo& nextSubmit, const asset::SBufferRange& bufferRange, IUpstreamingDataProducer& callback) { + if (!m_defaultUploadBuffer) + { + m_logger.log("no staging buffer available for upload. check `upstreamSize` passed to `IUtilities::create`",system::ILogger::ELL_ERROR); + return false; + } if (!bufferRange.isValid() || !bufferRange.buffer->getCreationParams().usage.hasFlags(asset::IBuffer::EUF_TRANSFER_DST_BIT)) { m_logger.log("Invalid `bufferRange` or buffer has no `EUF_TRANSFER_DST_BIT` usage flag, cannot `updateBufferRangeViaStagingBuffer`!", system::ILogger::ELL_ERROR); @@ -623,6 +632,11 @@ class NBL_API2 IUtilities : public core::IReferenceCounted template requires std::is_same_v, SIntendedSubmitInfo> inline bool downloadBufferRangeViaStagingBuffer(const std::function& consumeCallback, IntendedSubmitInfo&& nextSubmit, const asset::SBufferRange& srcBufferRange) { + if (!m_defaultDownloadBuffer) + { + m_logger.log("no staging buffer available for download. check `downstreamSize` passed to `IUtilities::create`",system::ILogger::ELL_ERROR); + return false; + } if (!srcBufferRange.isValid() || !srcBufferRange.buffer->getCreationParams().usage.hasFlags(asset::IBuffer::EUF_TRANSFER_SRC_BIT)) { m_logger.log("Invalid `srcBufferRange` or buffer has no `EUF_TRANSFER_SRC_BIT` usage flag, cannot `downloadBufferRangeViaStagingBuffer`!",system::ILogger::ELL_ERROR); diff --git a/smoke/CMakeLists.txt b/smoke/CMakeLists.txt index a44374714d..c560e56a0f 100644 --- a/smoke/CMakeLists.txt +++ b/smoke/CMakeLists.txt @@ -28,6 +28,7 @@ find_package(Nabla REQUIRED CONFIG add_executable(smoke main.cpp pch.hpp cdb.ps1) target_link_libraries(smoke PRIVATE Nabla::Nabla) +target_compile_definitions(smoke PRIVATE _AFXDLL) target_precompile_headers(smoke PRIVATE pch.hpp) set(CMAKE_CTEST_ARGUMENTS --verbose) diff --git a/smoke/main.cpp b/smoke/main.cpp index 2b1863d404..530b29adae 100644 --- a/smoke/main.cpp +++ b/smoke/main.cpp @@ -1,3 +1,5 @@ +#include + #define ENABLE_SMOKE using namespace nbl; @@ -36,7 +38,25 @@ class Smoke final : public system::IApplicationFramework return false; } - exportGpuProfiles(); + if (!AfxWinInit(GetModuleHandle(nullptr), nullptr, GetCommandLineA(), 0)) + { + std::cerr << "[ERROR]: Could not init AFX, terminating!\n"; + return false; + } + + try { + createAfxDummyWindow(320, 240, nullptr, _T("Dummy 1")); + exportGpuProfiles(); + createAfxDummyWindow(320, 240, nullptr, _T("Dummy 2")); + } + catch (const std::exception& e) { + std::cerr << "[ERROR]: " << e.what() << '\n'; + return false; + } + catch (...) { + std::cerr << "[ERROR]: Unknown exception!\n"; + return false; + } return true; } @@ -44,37 +64,60 @@ class Smoke final : public system::IApplicationFramework void workLoopBody() override {} bool keepRunning() override { return false; } + bool onAppTerminated() override + { + AfxWinTerm(); + return true; + } + private: static void exportGpuProfiles() { - std::string arg2 = "-o"; - std::string buf; - std::string arg1; - std::string arg3; + std::string buf, arg1, arg2 = "-o", arg3; for (size_t i = 0;; i++) { - auto stringifiedIndex = std::to_string(i); - arg1 = "--json=" + stringifiedIndex; - arg3 = "device_" + stringifiedIndex + ".json"; - std::array args = { arg1.data(), arg2.data(), arg3.data() }; + auto six = std::to_string(i); + arg1 = "--json=" + six; + arg3 = "device_" + six + ".json"; + auto args = std::to_array({ arg1.data(), arg2.data(), arg3.data()}); int code = nbl::video::vulkaninfo(args); if (code != 0) break; - // print out file content std::ifstream input(arg3); while (std::getline(input, buf)) - { std::cout << buf << "\n"; - } std::cout << "\n\n"; } } + + static bool createAfxDummyWindow(int w, int h, HWND parent, LPCTSTR windowName) + { + CWnd wnd; + LPCTSTR cls = AfxRegisterWndClass(0, ::LoadCursor(nullptr, IDC_ARROW)); + if (!cls) return false; + + if (!wnd.CreateEx(0, cls, windowName, WS_POPUP | WS_VISIBLE, 0, 0, w, h, parent, nullptr)) + return false; + + MSG msg {}; + const ULONGLONG end = GetTickCount64() + 1000; + while (GetTickCount64() < end) { + while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + Sleep(1); + } + + wnd.DestroyWindow(); + return true; + } }; NBL_MAIN_FUNC(Smoke) diff --git a/src/nbl/asset/utils/IShaderCompiler.cpp b/src/nbl/asset/utils/IShaderCompiler.cpp index e60bf31b5c..982f78ef6d 100644 --- a/src/nbl/asset/utils/IShaderCompiler.cpp +++ b/src/nbl/asset/utils/IShaderCompiler.cpp @@ -3,7 +3,6 @@ // For conditions of distribution and use, see copyright notice in nabla.h #include "nbl/asset/utils/IShaderCompiler.h" #include "nbl/asset/utils/shadercUtils.h" -#include "nbl/asset/utils/shaderCompiler_serialization.h" #include #include @@ -11,10 +10,258 @@ #include #include +#include "nlohmann/json.hpp" + +using json = nlohmann::json; +using SEntry = nbl::asset::IShaderCompiler::CCache::SEntry; using namespace nbl; using namespace nbl::asset; +// -> serialization +// SMacroData, simple container used in SPreprocessorArgs +namespace nbl::system::json { + template<> + struct adl_serializer + { + using value_t = IShaderCompiler::SMacroDefinition; + + static inline void to_json(::json& j, const value_t& p) + { + j = ::json{ + { "identifier", p.identifier }, + { "definition", p.definition }, + }; + } + + static inline void from_json(const ::json& j, value_t& p) + { + j.at("identifier").get_to(p.identifier); + j.at("definition").get_to(p.definition); + } + }; +} +NBL_JSON_IMPL_BIND_ADL_SERIALIZER(::nbl::system::json::adl_serializer) + +// SPreprocessorData, holds serialized info for Preprocessor options used during compilation +namespace nbl::system::json { + template<> + struct adl_serializer + { + using value_t = SEntry::SPreprocessorArgs; + + static inline void to_json(::json& j, const value_t& p) + { + j = ::json{ + { "sourceIdentifier", p.sourceIdentifier }, + { "extraDefines", p.extraDefines}, + }; + } + + static inline void from_json(const ::json& j, value_t& p) + { + j.at("sourceIdentifier").get_to(p.sourceIdentifier); + j.at("extraDefines").get_to(p.extraDefines); + } + }; +} +NBL_JSON_IMPL_BIND_ADL_SERIALIZER(::nbl::system::json::adl_serializer) + +// Optimizer pass has its own method for easier vector serialization +namespace nbl::system::json { + template<> + struct adl_serializer + { + using value_t = ISPIRVOptimizer::E_OPTIMIZER_PASS; + + static inline void to_json(::json& j, const value_t& p) + { + uint32_t value = static_cast(p); + j = ::json{ + { "optPass", value }, + }; + } + + static inline void from_json(const ::json& j, value_t& p) + { + uint32_t aux; + j.at("optPass").get_to(aux); + p = static_cast(aux); + } + }; +} +NBL_JSON_IMPL_BIND_ADL_SERIALIZER(::nbl::system::json::adl_serializer) + +// SCompilerArgs, holds serialized info for all Compilation options +namespace nbl::system::json { + template<> + struct adl_serializer + { + using value_t = SEntry::SCompilerArgs; + + static inline void to_json(::json& j, const value_t& p) + { + uint32_t shaderStage = static_cast(p.stage); + uint32_t spirvVersion = static_cast(p.targetSpirvVersion); + uint32_t debugFlags = static_cast(p.debugInfoFlags.value); + + j = ::json{ + { "shaderStage", shaderStage }, + { "spirvVersion", spirvVersion }, + { "optimizerPasses", p.optimizerPasses }, + { "debugFlags", debugFlags }, + { "preprocessorArgs", p.preprocessorArgs }, + }; + } + + static inline void from_json(const ::json& j, value_t& p) + { + uint32_t shaderStage, spirvVersion, debugFlags; + j.at("shaderStage").get_to(shaderStage); + j.at("spirvVersion").get_to(spirvVersion); + j.at("optimizerPasses").get_to(p.optimizerPasses); + j.at("debugFlags").get_to(debugFlags); + j.at("preprocessorArgs").get_to(p.preprocessorArgs); + p.stage = static_cast(shaderStage); + p.targetSpirvVersion = static_cast(spirvVersion); + p.debugInfoFlags = core::bitflag(debugFlags); + } + }; +} +NBL_JSON_IMPL_BIND_ADL_SERIALIZER(::nbl::system::json::adl_serializer) + +// Serialize clock's time point +using time_point_t = nbl::system::IFileBase::time_point_t; +namespace nbl::system::json { + template<> + struct adl_serializer + { + using value_t = time_point_t; + + static inline void to_json(::json& j, const value_t& p) + { + auto ticks = p.time_since_epoch().count(); + j = ::json{ + { "ticks", ticks }, + }; + } + + static inline void from_json(const ::json& j, value_t& p) + { + uint64_t ticks; + j.at("ticks").get_to(ticks); + p = time_point_t(time_point_t::clock::duration(ticks)); + } + }; +} +NBL_JSON_IMPL_BIND_ADL_SERIALIZER(::nbl::system::json::adl_serializer) + +// SDependency serialization. Dependencies will be saved in a vector for easier vectorization +namespace nbl::system::json { + template<> + struct adl_serializer + { + using value_t = SEntry::SPreprocessingDependency; + + static inline void to_json(::json& j, const value_t& p) + { + j = ::json{ + { "requestingSourceDir", p.requestingSourceDir }, + { "identifier", p.identifier }, + { "hash", p.hash.data }, + { "standardInclude", p.standardInclude }, + }; + } + + static inline void from_json(const ::json& j, value_t& p) + { + j.at("requestingSourceDir").get_to(p.requestingSourceDir); + j.at("identifier").get_to(p.identifier); + j.at("hash").get_to(p.hash.data); + j.at("standardInclude").get_to(p.standardInclude); + } + }; +} +NBL_JSON_IMPL_BIND_ADL_SERIALIZER(::nbl::system::json::adl_serializer) + +// We serialize shader creation parameters into a json, along with indexing info into the .bin buffer where the cache is serialized +struct CPUShaderCreationParams { + IShader::E_SHADER_STAGE stage; + std::string filepathHint; + uint64_t codeByteSize = 0; + uint64_t offset = 0; // Offset into the serialized .bin for the Cache where code starts + + CPUShaderCreationParams(IShader::E_SHADER_STAGE _stage, std::string_view _filepathHint, uint64_t _codeByteSize, uint64_t _offset) + : stage(_stage), filepathHint(_filepathHint), codeByteSize(_codeByteSize), offset(_offset) {} + CPUShaderCreationParams() {}; +}; + +namespace nbl::system::json { + template<> + struct adl_serializer + { + using value_t = CPUShaderCreationParams; + + static inline void to_json(::json& j, const value_t& p) + { + uint32_t stage = static_cast(p.stage); + j = ::json{ + { "stage", stage }, + { "filepathHint", p.filepathHint }, + { "codeByteSize", p.codeByteSize }, + { "offset", p.offset }, + }; + } + + static inline void from_json(const ::json& j, value_t& p) + { + uint32_t stage; + j.at("stage").get_to(stage); + j.at("filepathHint").get_to(p.filepathHint); + j.at("codeByteSize").get_to(p.codeByteSize); + j.at("offset").get_to(p.offset); + p.stage = static_cast(stage); + } + }; +} +NBL_JSON_IMPL_BIND_ADL_SERIALIZER(::nbl::system::json::adl_serializer) + +// Serialize SEntry, keeping some fields as extra serialization to keep them separate on disk +namespace nbl::system::json { + template<> + struct adl_serializer + { + using value_t = SEntry; + + static inline void to_json(::json& j, const value_t& p) + { + j = ::json{ + { "mainFileContents", p.mainFileContents }, + { "compilerArgs", p.compilerArgs }, + { "hash", p.hash.data }, + { "lookupHash", p.lookupHash }, + { "dependencies", p.dependencies }, + { "uncompressedContentHash", p.uncompressedContentHash.data }, + { "uncompressedSize", p.uncompressedSize }, + }; + } + + static inline void from_json(const ::json& j, value_t& p) + { + j.at("mainFileContents").get_to(p.mainFileContents); + j.at("compilerArgs").get_to(p.compilerArgs); + j.at("hash").get_to(p.hash.data); + j.at("lookupHash").get_to(p.lookupHash); + j.at("dependencies").get_to(p.dependencies); + j.at("uncompressedContentHash").get_to(p.uncompressedContentHash.data); + j.at("uncompressedSize").get_to(p.uncompressedSize); + p.spirv = nullptr; + } + }; +} +NBL_JSON_IMPL_BIND_ADL_SERIALIZER(::nbl::system::json::adl_serializer) +// <- serialization + IShaderCompiler::IShaderCompiler(core::smart_refctd_ptr&& system) : m_system(std::move(system)) { diff --git a/src/nbl/asset/utils/shaderCompiler_serialization.h b/src/nbl/asset/utils/shaderCompiler_serialization.h deleted file mode 100644 index 6ad33a2ff5..0000000000 --- a/src/nbl/asset/utils/shaderCompiler_serialization.h +++ /dev/null @@ -1,196 +0,0 @@ -#ifndef _NBL_ASSET_SHADER_COMPILER_SERIALIZATION_H_INCLUDED_ -#define _NBL_ASSET_SHADER_COMPILER_SERIALIZATION_H_INCLUDED_ - -#include "nbl/asset/utils/IShaderCompiler.h" -#include "nlohmann/json.hpp" - -using json = nlohmann::json; -using SEntry = nbl::asset::IShaderCompiler::CCache::SEntry; - - -namespace nbl::asset -{ - -// TODO: use NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE whenever possible - -// SMacroData, simple container used in SPreprocessorArgs - -inline void to_json(json& j, const IShaderCompiler::SMacroDefinition& macroData) -{ - j = json{ - { "identifier", macroData.identifier }, - { "definition", macroData.definition }, - }; -} - -inline void from_json(const json& j, IShaderCompiler::SMacroDefinition& macroData) -{ - j.at("identifier").get_to(macroData.identifier); - j.at("definition").get_to(macroData.definition); -} - -// SPreprocessorData, holds serialized info for Preprocessor options used during compilation -inline void to_json(json& j, const SEntry::SPreprocessorArgs& preprocArgs) -{ - j = json{ - { "sourceIdentifier", preprocArgs.sourceIdentifier }, - { "extraDefines", preprocArgs.extraDefines}, - }; -} - -inline void from_json(const json& j, SEntry::SPreprocessorArgs& preprocArgs) -{ - j.at("sourceIdentifier").get_to(preprocArgs.sourceIdentifier); - j.at("extraDefines").get_to(preprocArgs.extraDefines); -} - -// Optimizer pass has its own method for easier vector serialization - -inline void to_json(json& j, const ISPIRVOptimizer::E_OPTIMIZER_PASS& optPass) -{ - uint32_t value = static_cast(optPass); - j = json{ - { "optPass", value }, - }; -} - -inline void from_json(const json& j, ISPIRVOptimizer::E_OPTIMIZER_PASS& optPass) -{ - uint32_t aux; - j.at("optPass").get_to(aux); - optPass = static_cast(aux); -} - -// SCompilerArgs, holds serialized info for all Compilation options - -inline void to_json(json& j, const SEntry::SCompilerArgs& compilerData) -{ - uint32_t shaderStage = static_cast(compilerData.stage); - uint32_t spirvVersion = static_cast(compilerData.targetSpirvVersion); - uint32_t debugFlags = static_cast(compilerData.debugInfoFlags.value); - - j = json { - { "shaderStage", shaderStage }, - { "spirvVersion", spirvVersion }, - { "optimizerPasses", compilerData.optimizerPasses }, - { "debugFlags", debugFlags }, - { "preprocessorArgs", compilerData.preprocessorArgs }, - }; -} - -inline void from_json(const json& j, SEntry::SCompilerArgs& compilerData) -{ - uint32_t shaderStage, spirvVersion, debugFlags; - j.at("shaderStage").get_to(shaderStage); - j.at("spirvVersion").get_to(spirvVersion); - j.at("optimizerPasses").get_to(compilerData.optimizerPasses); - j.at("debugFlags").get_to(debugFlags); - j.at("preprocessorArgs").get_to(compilerData.preprocessorArgs); - compilerData.stage = static_cast(shaderStage); - compilerData.targetSpirvVersion = static_cast(spirvVersion); - compilerData.debugInfoFlags = core::bitflag(debugFlags); -} - -// Serialize clock's time point -using time_point_t = nbl::system::IFileBase::time_point_t; - -inline void to_json(json& j, const time_point_t& timePoint) -{ - auto ticks = timePoint.time_since_epoch().count(); - j = json{ - { "ticks", ticks }, - }; -} - -inline void from_json(const json& j, time_point_t& timePoint) -{ - uint64_t ticks; - j.at("ticks").get_to(ticks); - timePoint = time_point_t(time_point_t::clock::duration(ticks)); -} - -// SDependency serialization. Dependencies will be saved in a vector for easier vectorization - -inline void to_json(json& j, const SEntry::SPreprocessingDependency& dependency) -{ - j = json{ - { "requestingSourceDir", dependency.requestingSourceDir }, - { "identifier", dependency.identifier }, - { "hash", dependency.hash.data }, - { "standardInclude", dependency.standardInclude }, - }; -} - -inline void from_json(const json& j, SEntry::SPreprocessingDependency& dependency) -{ - j.at("requestingSourceDir").get_to(dependency.requestingSourceDir); - j.at("identifier").get_to(dependency.identifier); - j.at("hash").get_to(dependency.hash.data); - j.at("standardInclude").get_to(dependency.standardInclude); -} - -// We serialize shader creation parameters into a json, along with indexing info into the .bin buffer where the cache is serialized - -struct CPUShaderCreationParams { - IShader::E_SHADER_STAGE stage; - std::string filepathHint; - uint64_t codeByteSize = 0; - uint64_t offset = 0; // Offset into the serialized .bin for the Cache where code starts - - CPUShaderCreationParams(IShader::E_SHADER_STAGE _stage, std::string_view _filepathHint, uint64_t _codeByteSize, uint64_t _offset) - : stage(_stage), filepathHint(_filepathHint), codeByteSize(_codeByteSize), offset(_offset) - {} - - CPUShaderCreationParams() {}; -}; - -inline void to_json(json& j, const CPUShaderCreationParams& creationParams) -{ - uint32_t stage = static_cast(creationParams.stage); - j = json{ - { "stage", stage }, - { "filepathHint", creationParams.filepathHint }, - { "codeByteSize", creationParams.codeByteSize }, - { "offset", creationParams.offset }, - }; -} - -inline void from_json(const json& j, CPUShaderCreationParams& creationParams) -{ - uint32_t stage; - j.at("stage").get_to(stage); - j.at("filepathHint").get_to(creationParams.filepathHint); - j.at("codeByteSize").get_to(creationParams.codeByteSize); - j.at("offset").get_to(creationParams.offset); - creationParams.stage = static_cast(stage); -} - -// Serialize SEntry, keeping some fields as extra serialization to keep them separate on disk - -inline void to_json(json& j, const SEntry& entry) -{ - j = json{ - { "mainFileContents", entry.mainFileContents }, - { "compilerArgs", entry.compilerArgs }, - { "hash", entry.hash.data }, - { "lookupHash", entry.lookupHash }, - { "dependencies", entry.dependencies }, - { "uncompressedContentHash", entry.uncompressedContentHash.data }, - { "uncompressedSize", entry.uncompressedSize }, - }; -} - -inline void from_json(const json& j, SEntry& entry) -{ - j.at("mainFileContents").get_to(entry.mainFileContents); - j.at("compilerArgs").get_to(entry.compilerArgs); - j.at("hash").get_to(entry.hash.data); - j.at("lookupHash").get_to(entry.lookupHash); - j.at("dependencies").get_to(entry.dependencies); - j.at("uncompressedContentHash").get_to(entry.uncompressedContentHash.data); - j.at("uncompressedSize").get_to(entry.uncompressedSize); - entry.spirv = nullptr; -} - -} -#endif \ No newline at end of file diff --git a/src/nbl/video/ILogicalDevice.cpp b/src/nbl/video/ILogicalDevice.cpp index 7c3f5dbb81..81f880cfeb 100644 --- a/src/nbl/video/ILogicalDevice.cpp +++ b/src/nbl/video/ILogicalDevice.cpp @@ -360,9 +360,7 @@ core::smart_refctd_ptr ILogicalDevice::compileShader(const SShad commonCompileOptions.preprocessorOptions.extraDefines = creationParams.extraDefines; commonCompileOptions.stage = creationParams.stage; - commonCompileOptions.debugInfoFlags = - asset::IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_SOURCE_BIT | - asset::IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_TOOL_BIT; + commonCompileOptions.debugInfoFlags = creationParams.debugInfoFlags; commonCompileOptions.spirvOptimizer = creationParams.optimizer; commonCompileOptions.preprocessorOptions.targetSpirvVersion = m_physicalDevice->getLimits().spirvVersion; diff --git a/src/nbl/video/utilities/IUtilities.cpp b/src/nbl/video/utilities/IUtilities.cpp index 46bda8a227..f6db104aa2 100644 --- a/src/nbl/video/utilities/IUtilities.cpp +++ b/src/nbl/video/utilities/IUtilities.cpp @@ -11,6 +11,11 @@ bool IUtilities::updateImageViaStagingBuffer( const std::span regions ) { + if (!m_defaultUploadBuffer) + { + m_logger.log("no staging buffer available for upload. check `upstreamSize` passed to `IUtilities::create`",system::ILogger::ELL_ERROR); + return false; + } auto* scratch = commonTransferValidation(intendedNextSubmit); if (!scratch) return false; @@ -164,6 +169,11 @@ bool IUtilities::downloadImageViaStagingBuffer( void* dest, const std::span regions ) { + if (!m_defaultDownloadBuffer) + { + m_logger.log("no staging buffer available for download. check `downstreamSize` passed to `IUtilities::create`",system::ILogger::ELL_ERROR); + return false; + } if (regions.empty()) return false; diff --git a/tools/nsc/main.cpp b/tools/nsc/main.cpp index c4ce43b326..f1e623bcf8 100644 --- a/tools/nsc/main.cpp +++ b/tools/nsc/main.cpp @@ -8,7 +8,7 @@ #include "nbl/asset/metadata/CHLSLMetadata.h" #include "nlohmann/json.hpp" -using json = nlohmann::json; +using json = ::nlohmann::json; using namespace nbl; using namespace nbl::system; @@ -34,7 +34,7 @@ class ShaderCompiler final : public system::IApplicationFramework if (argv[1] == "--dump-build-info") { - json j; + ::json j; auto& modules = j["modules"]; @@ -145,6 +145,7 @@ class ShaderCompiler final : public system::IApplicationFramework return strings; }; + // TODO: replace this parse crap with argparse or something auto findOutputFlag = [&](const std::string_view& outputFlag) { return std::find_if(m_arguments.begin(), m_arguments.end(), [&](const std::string& argument) @@ -299,7 +300,7 @@ class ShaderCompiler final : public system::IApplicationFramework options.preprocessorOptions.sourceIdentifier = sourceIdentifier; options.preprocessorOptions.logger = m_logger.get(); - options.debugInfoFlags = core::bitflag(asset::IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_TOOL_BIT); + options.debugInfoFlags = core::bitflag(asset::IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_NONE); // pass explicitly to CLI if you want them options.dxcOptions = std::span(m_arguments); auto includeFinder = make_smart_refctd_ptr(smart_refctd_ptr(m_system));