diff --git a/.github/workflows/build-xmake.yml b/.github/workflows/build-xmake.yml index e5565a61e..6ae5aa5e3 100644 --- a/.github/workflows/build-xmake.yml +++ b/.github/workflows/build-xmake.yml @@ -60,6 +60,12 @@ jobs: fi brew install molten-vk ninja cmake xmake curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + sudo xcode-select -switch /Applications/Xcode_16.1.app + echo "Check the relevant software versions" + brew --version + xcodebuild -version + clang++ --version + echo "Check End" - name: "Configure and Build" run: | xmake lua setup.lua diff --git a/include/luisa/backends/ext/dx_hdr_ext.hpp b/include/luisa/backends/ext/dx_hdr_ext.hpp new file mode 100644 index 000000000..ecb85b2c4 --- /dev/null +++ b/include/luisa/backends/ext/dx_hdr_ext.hpp @@ -0,0 +1,9 @@ +#pragma once +#include +#include +#include +namespace luisa::compute { +Swapchain DXHDRExt::create_swapchain(const Stream &stream, const DXSwapchainOption &option) noexcept { + return Swapchain{stream.device(), create_swapchain(option, stream.handle())}; +} +}// namespace luisa::compute \ No newline at end of file diff --git a/include/luisa/backends/ext/dx_hdr_ext_interface.h b/include/luisa/backends/ext/dx_hdr_ext_interface.h new file mode 100644 index 000000000..5aa89e04e --- /dev/null +++ b/include/luisa/backends/ext/dx_hdr_ext_interface.h @@ -0,0 +1,87 @@ +#pragma once +#include + +namespace luisa::compute { +class Swapchain; +class Stream; +class DXHDRExt : public DeviceExtension { +public: + enum class DisplayCurve { + sRGB = 0,// The display expects an sRGB signal. + ST2084, // The display expects an HDR10 signal. + None // The display expects a linear signal. + }; + enum class SwapChainBitDepth { + _8 = 0, + _10, + _16, + }; + struct DisplayChromaticities { + float RedX{0.f}; + float RedY{0.f}; + float GreenX{0.f}; + float GreenY{0.f}; + float BlueX{0.f}; + float BlueY{0.f}; + float WhiteX{0.f}; + float WhiteY{0.f}; + }; + struct DXSwapchainOption { + uint64_t window; + uint2 size; + PixelStorage storage = PixelStorage::HALF4; + bool wants_vsync = true; + uint back_buffer_count = 2; + }; + + enum class ColorSpace : uint { + RGB_FULL_G22_NONE_P709 = 0, + RGB_FULL_G10_NONE_P709 = 1, + RGB_STUDIO_G22_NONE_P709 = 2, + RGB_STUDIO_G22_NONE_P2020 = 3, + RESERVED = 4, + YCBCR_FULL_G22_NONE_P709_X601 = 5, + YCBCR_STUDIO_G22_LEFT_P601 = 6, + YCBCR_FULL_G22_LEFT_P601 = 7, + YCBCR_STUDIO_G22_LEFT_P709 = 8, + YCBCR_FULL_G22_LEFT_P709 = 9, + YCBCR_STUDIO_G22_LEFT_P2020 = 10, + YCBCR_FULL_G22_LEFT_P2020 = 11, + RGB_FULL_G2084_NONE_P2020 = 12, + YCBCR_STUDIO_G2084_LEFT_P2020 = 13, + RGB_STUDIO_G2084_NONE_P2020 = 14, + YCBCR_STUDIO_G22_TOPLEFT_P2020 = 15, + YCBCR_STUDIO_G2084_TOPLEFT_P2020 = 16, + RGB_FULL_G22_NONE_P2020 = 17, + YCBCR_STUDIO_GHLG_TOPLEFT_P2020 = 18, + YCBCR_FULL_GHLG_TOPLEFT_P2020 = 19, + RGB_STUDIO_G24_NONE_P709 = 20, + RGB_STUDIO_G24_NONE_P2020 = 21, + YCBCR_STUDIO_G24_LEFT_P709 = 22, + YCBCR_STUDIO_G24_LEFT_P2020 = 23, + YCBCR_STUDIO_G24_TOPLEFT_P2020 = 24, + CUSTOM = 0xFFFFFFFF + }; + + struct Meta { + ColorSpace color_space; + DisplayChromaticities chromaticities; + }; + + [[nodiscard]] virtual SwapchainCreationInfo create_swapchain( + const DXSwapchainOption &option, + uint64_t stream_handle) noexcept = 0; + virtual Meta set_hdr_meta_data( + uint64_t swapchain_handle, + float max_output_nits = 1000.0f, + float min_output_nits = 0.001f, + float max_cll = 2000.0f, + float max_fall = 500.0f, + const DisplayChromaticities *custom_chroma = nullptr) noexcept = 0; + static constexpr luisa::string_view name = "DXHDRExt"; + [[nodiscard]] Swapchain create_swapchain(const Stream &stream, const DXSwapchainOption &option) noexcept; + +protected: + ~DXHDRExt() = default; +}; +}// namespace luisa::compute \ No newline at end of file diff --git a/include/luisa/core/basic_types.h b/include/luisa/core/basic_types.h index cf0d4d0a8..cc561039b 100644 --- a/include/luisa/core/basic_types.h +++ b/include/luisa/core/basic_types.h @@ -20,7 +20,7 @@ template static constexpr size_t vector_alignment_v = vector_alignment::value; /// Vector storage only allows size of 2, 3, 4 -template +template struct VectorStorage { static_assert(always_false_v, "Invalid vector storage"); }; @@ -28,7 +28,8 @@ struct VectorStorage { /// Vector storage of size 2 template struct alignas(vector_alignment_v) VectorStorage { - T x, y; + T x {}; + T y {}; explicit constexpr VectorStorage(T s = {}) noexcept : x{s}, y{s} {} constexpr VectorStorage(T x, T y) noexcept : x{x}, y{y} {} #include @@ -37,7 +38,9 @@ struct alignas(vector_alignment_v) VectorStorage { /// Vector storage of size 3 template struct alignas(vector_alignment_v) VectorStorage { - T x, y, z; + T x {}; + T y {}; + T z {}; explicit constexpr VectorStorage(T s = {}) noexcept : x{s}, y{s}, z{s} {} constexpr VectorStorage(T x, T y, T z) noexcept : x{x}, y{y}, z{z} {} #include @@ -46,7 +49,10 @@ struct alignas(vector_alignment_v) VectorStorage { /// Vector storage of size 4 template struct alignas(vector_alignment_v) VectorStorage { - T x, y, z, w; + T x {}; + T y {}; + T z {}; + T w {}; explicit constexpr VectorStorage(T s = {}) noexcept : x{s}, y{s}, z{s}, w{s} {} constexpr VectorStorage(T x, T y, T z, T w) noexcept : x{x}, y{y}, z{z}, w{w} {} #include @@ -63,18 +69,37 @@ struct alignas(vector_alignment_v) VectorStorage { * @tparam T bool/float/int/uint * @tparam N 2/3/4 */ -template +template struct Vector : public detail::VectorStorage { - static constexpr auto dimension = N; - static Vector zero() noexcept { return Vector(static_cast(0)); } - static Vector one() noexcept { return Vector(static_cast(1)); } using value_type = T; - using Storage = detail::VectorStorage; - static_assert(is_scalar_v, "Invalid vector type"); + using size_type = std::size_t; + using reference = value_type &; + using const_reference = const value_type &; + using Storage = detail::VectorStorage; + using Storage::VectorStorage; // introduce base class constructor function + + static_assert(is_scalar_v, "Invalid vector type"); static_assert(N == 2 || N == 3 || N == 4, "Invalid vector dimension"); - using Storage::VectorStorage; - [[nodiscard]] constexpr T &operator[](size_t index) noexcept { return (&(this->x))[index]; } - [[nodiscard]] constexpr const T &operator[](size_t index) const noexcept { return (&(this->x))[index]; } + + static constexpr size_type dimension { N }; + + static Vector zero() noexcept { + return Vector(static_cast(0)); + } + + static Vector one() noexcept { + return Vector(static_cast(1)); + } + + [[nodiscard]] + constexpr reference operator[](size_type index) noexcept { + return (&(this->x))[index]; + } + + [[nodiscard]] + constexpr const_reference operator[](size_type index) const noexcept { + return (&(this->x))[index]; + } }; template @@ -571,8 +596,6 @@ LUISA_MAKE_TYPE_N(bool) LUISA_MAKE_TYPE_N(float) LUISA_MAKE_TYPE_N(int) LUISA_MAKE_TYPE_N(uint) -LUISA_MAKE_TYPE_N(byte) -LUISA_MAKE_TYPE_N(ubyte) LUISA_MAKE_TYPE_N(short) LUISA_MAKE_TYPE_N(ushort) LUISA_MAKE_TYPE_N(slong) diff --git a/include/luisa/core/dynamic_module.h b/include/luisa/core/dynamic_module.h index a8f5a1041..559810883 100644 --- a/include/luisa/core/dynamic_module.h +++ b/include/luisa/core/dynamic_module.h @@ -9,7 +9,7 @@ namespace luisa { /** * @brief Dynamic module loader - * + * */ class LC_CORE_API DynamicModule : concepts::Noncopyable { @@ -29,7 +29,7 @@ class LC_CORE_API DynamicModule : concepts::Noncopyable { void dispose() noexcept; /** * @brief Return function pointer of given name - * + * * @tparam F function type * @param name name of function * @return pointer to function @@ -42,9 +42,9 @@ class LC_CORE_API DynamicModule : concepts::Noncopyable { /** * @brief Return address of given name - * + * * @param name - * @return void* + * @return void* */ [[nodiscard]] void *address(std::string_view name) const noexcept { return dynamic_module_find_symbol(_handle, name); @@ -52,7 +52,7 @@ class LC_CORE_API DynamicModule : concepts::Noncopyable { /** * @brief Invoke function - * + * * @tparam F function type * @tparam Args function args * @param name name of function @@ -67,12 +67,12 @@ class LC_CORE_API DynamicModule : concepts::Noncopyable { /** * @brief Apply function to each element - * + * * @tparam F function type * @tparam Tuple tuple type * @param name name of function * @param t tuple to be applied - * @return decltype(auto) + * @return decltype(auto) */ template decltype(auto) apply(std::string_view name, Tuple &&t) const noexcept { @@ -81,15 +81,15 @@ class LC_CORE_API DynamicModule : concepts::Noncopyable { /** * @brief Add dynamic module search path - * - * @param path + * + * @param path */ static void add_search_path(const std::filesystem::path &path) noexcept; /** * @brief Remove dynamic module search path - * - * @param path + * + * @param path */ static void remove_search_path(const std::filesystem::path &path) noexcept; @@ -108,7 +108,9 @@ class LC_CORE_API DynamicModule : concepts::Noncopyable { * @return The module if successfully loaded, otherwise a nullopt */ [[nodiscard]] static DynamicModule load( - const std::filesystem::path &folder, std::string_view name) noexcept; + const luisa::filesystem::path &folder, + std::string_view name + ) noexcept; }; }// namespace luisa diff --git a/include/luisa/runtime/context.h b/include/luisa/runtime/context.h index a4550feca..da2284863 100644 --- a/include/luisa/runtime/context.h +++ b/include/luisa/runtime/context.h @@ -26,7 +26,7 @@ class LC_RUNTIME_API Context { luisa::shared_ptr _impl; public: - explicit Context(luisa::shared_ptr impl) noexcept; + explicit Context(luisa::shared_ptr impl) noexcept; // program_path can be first arg from main entry explicit Context(luisa::string_view program_path) noexcept; explicit Context(const char *program_path) noexcept diff --git a/include/luisa/runtime/swapchain.h b/include/luisa/runtime/swapchain.h index d37e171da..aa0eef8ff 100644 --- a/include/luisa/runtime/swapchain.h +++ b/include/luisa/runtime/swapchain.h @@ -23,6 +23,7 @@ class LC_RUNTIME_API Swapchain final : public Resource { private: friend class Device; friend class ResourceGenerator; + friend class DXHDRExt; PixelStorage _storage{}; Swapchain(DeviceInterface *device, const SwapchainCreationInfo &create_info) noexcept; Swapchain(DeviceInterface *device, const SwapchainOption &option, uint64_t stream_handle) noexcept; diff --git a/src/backends/common/hlsl/builtin/hlsl_builtin.hpp b/src/backends/common/hlsl/builtin/hlsl_builtin.hpp index 612777945..ec3dd540a 100644 --- a/src/backends/common/hlsl/builtin/hlsl_builtin.hpp +++ b/src/backends/common/hlsl/builtin/hlsl_builtin.hpp @@ -47,7 +47,7 @@ static HLSLCompressedHeader get_hlsl_builtin(luisa::string_view ss) { dict.try_emplace("bc7_trymode_137cs", HLSLCompressedHeader{bc7_trymode_137cs, 1814, 7852}); dict.try_emplace("bc7_trymode_456cs", HLSLCompressedHeader{bc7_trymode_456cs, 2391, 11171}); dict.try_emplace("hlsl_header", HLSLCompressedHeader{hlsl_header, 1411, 5596}); - dict.try_emplace("raytracing_header", HLSLCompressedHeader{raytracing_header, 868, 3614}); + dict.try_emplace("raytracing_header", HLSLCompressedHeader{raytracing_header, 881, 3650}); dict.try_emplace("tex2d_bindless", HLSLCompressedHeader{tex2d_bindless, 551, 4136}); dict.try_emplace("tex3d_bindless", HLSLCompressedHeader{tex3d_bindless, 507, 3535}); dict.try_emplace("compute_quad", HLSLCompressedHeader{compute_quad, 87, 138}); diff --git a/src/backends/common/hlsl/builtin/raytracing_header b/src/backends/common/hlsl/builtin/raytracing_header index 7bc4a2297..49e5d4d48 100644 --- a/src/backends/common/hlsl/builtin/raytracing_header +++ b/src/backends/common/hlsl/builtin/raytracing_header @@ -11,7 +11,7 @@ ray.TMin=rayDesc.v1; ray.TMax=rayDesc.v3; RayQuery<_CLOSEST_HIT_RAY_FLAG> q; q.TraceRayInline(accel,_CLOSEST_HIT_RAY_FLAG,mask,ray); -_Hit1 pl; +_Hit1 pl=(_Hit1)0; q.Proceed(); if(q.CommittedStatus()==COMMITTED_TRIANGLE_HIT){ pl.v0=q.CommittedInstanceIndex(); @@ -62,7 +62,7 @@ return ray; } template _Hit0 _GetCommitedHit(Q q){ -_Hit0 pl; +_Hit0 pl=(_Hit0)0; switch(q.CommittedStatus()){ case COMMITTED_TRIANGLE_HIT: pl.v0=q.CommittedInstanceIndex(); @@ -86,7 +86,7 @@ return pl; } template _Hit1 _GetTriangleCandidateHit(Q q){ -_Hit1 pl; +_Hit1 pl=(_Hit1)0; pl.v0=q.CandidateInstanceIndex(); pl.v1=q.CandidatePrimitiveIndex(); pl.v2=q.CandidateTriangleBarycentrics(); @@ -95,7 +95,7 @@ return pl; } template _Hit2 _GetProceduralCandidateHit(Q q){ -_Hit2 pl; +_Hit2 pl=(_Hit2)0; pl.v0=q.CandidateInstanceIndex(); pl.v1=q.CandidatePrimitiveIndex(); return pl; diff --git a/src/backends/common/hlsl/builtin/raytracing_header.cpp b/src/backends/common/hlsl/builtin/raytracing_header.cpp index 760c79364..d73eb22fe 100644 --- a/src/backends/common/hlsl/builtin/raytracing_header.cpp +++ b/src/backends/common/hlsl/builtin/raytracing_header.cpp @@ -1,3 +1,3 @@ namespace lc_hlsl{ -unsigned char raytracing_header[868]={120,218,237,87,223,111,218,48,16,126,175,212,255,193,83,95,64,66,8,210,110,83,75,169,148,133,20,162,1,129,36,221,84,77,85,228,38,110,103,53,56,224,24,214,172,237,255,62,59,191,72,66,10,76,219,180,151,62,180,114,238,206,231,239,190,59,159,143,35,23,221,97,130,128,173,12,117,83,53,45,123,160,89,182,33,95,219,151,67,185,15,106,233,202,190,212,13,69,181,245,137,60,189,82,159,51,169,249,89,155,216,19,67,87,212,222,149,33,15,249,82,27,105,150,246,69,53,235,135,7,71,169,107,121,124,253,154,91,89,81,212,137,101,95,106,70,114,180,60,238,217,42,255,51,85,217,80,6,165,147,242,24,205,129,220,83,141,231,63,1,200,194,57,226,24,129,1,195,233,18,209,240,60,219,54,214,199,234,5,176,135,138,157,234,100,207,235,108,219,177,35,144,146,51,18,10,103,104,54,247,32,67,231,194,43,129,51,4,172,139,195,3,123,128,89,27,216,22,133,14,82,60,63,64,1,171,241,125,140,127,99,114,47,59,14,242,16,133,12,251,196,100,116,233,176,37,69,0,10,105,195,2,20,134,61,20,56,141,37,38,12,204,96,240,80,127,58,60,48,98,161,80,242,67,249,255,166,78,241,61,38,221,59,207,135,236,184,150,108,106,174,90,205,213,183,214,77,163,240,221,46,125,75,55,245,196,73,15,83,228,8,24,27,126,164,146,31,169,228,71,42,248,177,70,28,74,166,107,103,82,248,184,150,30,119,162,48,98,202,43,43,245,2,44,184,205,162,25,209,198,77,53,226,241,210,171,197,196,84,238,104,8,126,4,40,1,36,38,125,238,69,62,38,212,119,16,114,107,66,129,239,106,139,166,226,207,102,152,49,228,154,12,178,101,80,171,119,187,138,62,226,117,100,169,61,219,50,52,121,220,31,170,194,185,160,123,238,113,166,186,185,77,26,9,24,36,14,210,136,139,30,35,167,194,164,157,55,153,80,204,23,120,85,178,145,242,54,22,197,144,220,123,232,19,164,161,131,8,163,216,9,50,203,227,188,37,15,223,138,52,47,200,11,80,6,233,68,58,61,57,253,240,81,58,125,47,84,156,102,196,107,135,196,65,191,188,90,141,197,43,0,236,116,245,86,147,157,77,118,182,212,96,161,181,20,106,47,201,195,98,239,52,144,48,77,3,9,223,210,208,217,100,103,159,52,236,232,215,191,151,161,6,200,214,83,158,45,11,100,112,250,136,125,245,169,39,238,100,109,10,22,117,192,89,143,73,1,62,191,179,169,46,166,61,186,180,137,214,205,105,51,62,35,3,43,151,174,36,49,93,191,249,152,151,180,133,164,96,35,9,201,207,84,34,154,143,232,18,163,228,204,72,24,231,166,235,174,93,197,217,225,146,48,47,145,132,36,115,85,221,121,18,198,98,160,149,156,77,147,167,174,5,108,206,81,236,1,185,92,16,209,244,148,42,163,238,20,252,192,204,249,94,213,136,133,161,3,3,4,170,251,241,217,127,107,199,237,100,117,82,73,207,45,69,240,161,179,1,189,106,78,249,23,97,180,50,152,210,94,48,249,196,3,151,30,59,75,119,181,114,186,125,30,146,233,122,172,225,185,78,153,83,32,113,177,203,13,75,73,79,222,225,44,226,212,108,75,196,169,201,182,196,165,54,187,223,209,178,101,185,170,119,7,42,69,129,70,115,132,187,164,208,123,45,84,233,175,134,186,23,188,149,143,93,62,236,71,185,94,3,20,160,26,81,231,1,46,14,152,192,199,39,31,177,60,223,40,140,186,104,174,101,7,25,28,17,97,228,98,219,115,118,235,251,94,50,226,190,189,97,229,241,182,252,107,105,251,104,91,182,46,60,92,197,89,54,125,198,54,219,232,187,220,60,59,214,173,129,54,238,199,233,251,5,64,150,165,243}; +unsigned char raytracing_header[881]={120,218,237,87,223,111,218,48,16,126,175,212,255,193,83,95,130,132,16,164,221,166,150,82,41,11,105,137,6,4,146,116,83,53,85,145,155,184,157,181,224,64,98,88,179,118,255,251,108,231,7,73,72,129,105,155,246,210,7,144,115,119,62,127,247,221,229,124,57,242,208,61,38,8,56,234,208,176,52,203,118,6,186,237,152,202,141,115,57,84,174,128,148,173,156,75,195,84,53,199,152,40,211,107,237,57,151,90,31,245,137,51,49,13,85,235,95,155,202,144,45,245,145,110,235,159,52,171,113,120,112,148,185,86,198,55,47,185,85,84,85,155,216,206,165,110,166,71,43,227,190,163,177,159,165,41,166,58,168,156,84,196,104,13,148,190,102,62,255,9,64,26,207,17,195,8,76,24,79,151,40,140,207,243,109,99,99,172,93,0,103,168,58,153,78,241,253,238,182,29,59,2,169,56,35,49,119,134,102,115,31,82,116,206,189,18,56,67,192,190,56,60,112,6,152,118,128,99,135,208,69,170,31,68,40,162,18,219,71,217,51,38,15,138,235,34,31,133,144,226,128,88,52,92,186,116,25,34,0,185,180,105,131,16,198,125,20,185,205,37,38,20,204,96,244,173,241,116,120,96,38,66,174,100,135,178,255,150,17,226,7,76,122,247,126,0,233,177,148,110,106,173,218,173,213,151,246,109,179,244,220,169,60,203,183,141,212,73,31,135,200,229,48,54,252,200,21,63,114,197,143,92,242,99,143,24,148,92,215,201,165,240,113,45,61,238,138,48,18,202,107,43,245,2,44,152,205,162,37,104,99,166,58,241,89,233,73,9,49,181,59,154,156,31,14,138,3,73,72,159,251,61,73,172,26,109,225,108,18,6,46,66,158,196,45,240,189,180,104,169,193,108,134,41,69,158,69,33,93,70,82,163,215,83,141,17,43,40,91,235,59,182,169,43,227,171,161,198,79,225,188,207,125,70,89,175,176,73,39,17,133,196,69,58,241,208,163,112,202,77,58,69,147,73,136,217,2,175,42,54,114,209,198,14,49,36,15,62,250,0,195,216,69,132,134,216,141,114,203,227,162,37,227,193,22,154,159,200,143,80,14,233,68,62,61,57,125,247,94,62,125,203,85,140,111,196,138,136,176,232,147,199,23,202,178,252,46,0,39,91,189,22,103,119,147,157,45,197,88,234,49,165,34,76,243,176,216,59,13,36,206,210,64,226,215,52,116,55,217,217,39,13,59,26,247,239,101,168,9,242,245,148,101,203,6,57,156,43,68,63,7,161,207,223,73,105,10,22,13,192,88,79,72,1,1,123,103,51,93,66,187,120,105,83,173,87,208,230,124,10,3,187,144,174,52,49,189,160,245,88,148,116,184,164,100,35,115,201,143,76,194,155,15,239,18,163,244,76,33,76,114,211,243,214,174,146,236,48,73,92,148,200,92,146,187,170,239,60,41,99,9,208,90,206,166,233,157,215,6,14,227,40,241,128,60,38,16,52,61,101,202,172,55,183,69,111,142,190,99,234,126,173,235,200,124,135,11,35,4,234,27,243,217,127,235,203,157,116,117,82,203,211,93,136,224,183,238,6,244,186,201,229,95,132,209,206,97,202,123,193,100,51,16,92,250,244,44,219,213,46,232,246,185,81,166,235,65,135,37,61,99,78,133,196,195,30,51,172,100,191,122,51,231,161,103,246,91,66,207,76,182,101,48,179,217,125,179,86,45,171,117,190,59,98,89,68,44,38,11,111,25,66,255,165,152,229,60,102,249,111,198,188,23,206,85,128,61,246,65,32,178,191,70,202,209,53,69,83,2,30,142,40,7,202,134,34,190,60,223,40,149,6,239,187,85,7,57,28,30,170,112,177,237,166,187,11,2,63,29,131,95,175,183,234,8,92,253,162,218,62,254,86,173,75,119,90,121,204,205,110,184,205,198,250,166,48,234,142,13,123,160,143,175,146,244,253,2,8,227,175,191}; } \ No newline at end of file diff --git a/src/backends/common/hlsl/hlsl_codegen_util.cpp b/src/backends/common/hlsl/hlsl_codegen_util.cpp index 159a7a959..ac496133c 100644 --- a/src/backends/common/hlsl/hlsl_codegen_util.cpp +++ b/src/backends/common/hlsl/hlsl_codegen_util.cpp @@ -1065,12 +1065,12 @@ void CodegenUtility::GetFunctionName(CallExpr const *expr, vstd::StringBuilder & str << "GroupMemoryBarrierWithGroupSync()"sv; return; case CallOp::RASTER_DISCARD: - LUISA_ASSERT(opt->funcType == CodegenStackData::FuncType::Pixel, "Raster-Discard can only be used in pixel shader"); + LUISA_ASSERT(opt->isPixelShader, "Raster-Discard can only be used in pixel shader"); str << "discard"; return; case CallOp::DDX: { if (opt->isRaster) { - LUISA_ASSERT(opt->funcType == CodegenStackData::FuncType::Pixel, "ddx can only be used in pixel shader"); + LUISA_ASSERT(opt->isPixelShader, "ddx can only be used in pixel shader"); str << "ddx"sv; } else { str << "_ddx"sv; @@ -1078,7 +1078,7 @@ void CodegenUtility::GetFunctionName(CallExpr const *expr, vstd::StringBuilder & } break; case CallOp::DDY: { if (opt->isRaster) { - LUISA_ASSERT(opt->funcType == CodegenStackData::FuncType::Pixel, "ddy can only be used in pixel shader"); + LUISA_ASSERT(opt->isPixelShader, "ddy can only be used in pixel shader"); str << "ddy"sv; } else { str << "_ddy"sv; @@ -1584,20 +1584,7 @@ void main(uint3 thdId:SV_GroupThreadId,uint3 dspId:SV_DispatchThreadID,uint3 grp callable(callable, func); } void CodegenUtility::CodegenVertex(Function vert, vstd::StringBuilder &result, bool cBufferNonEmpty) { - vstd::unordered_set callableMap; - auto gen = [&](auto &callable, Function func) -> void { - for (auto &&i : func.custom_callables()) { - if (callableMap.emplace(i.get()).second) { - Function f(i.get()); - callable(callable, f); - } - } - }; - auto callable = [&](auto &callable, Function func) -> void { - gen(callable, func); - CodegenFunction(func, result, cBufferNonEmpty); - }; - gen(callable, vert); + CodegenFunction(vert, result, cBufferNonEmpty); auto args = vert.arguments(); vstd::StringBuilder retName; auto retType = vert.return_type(); @@ -1634,20 +1621,7 @@ void CodegenUtility::CodegenVertex(Function vert, vstd::StringBuilder &result, b void CodegenUtility::CodegenPixel(Function pixel, vstd::StringBuilder &result, bool cBufferNonEmpty) { opt->isPixelShader = true; auto resetPixelShaderKey = vstd::scope_exit([&] { opt->isPixelShader = false; }); - vstd::unordered_set callableMap; - auto gen = [&](auto &callable, Function func) -> void { - for (auto &&i : func.custom_callables()) { - if (callableMap.emplace(i.get()).second) { - Function f(i.get()); - callable(callable, f); - } - } - }; - auto callable = [&](auto &callable, Function func) -> void { - gen(callable, func); - CodegenFunction(func, result, cBufferNonEmpty); - }; - gen(callable, pixel); + CodegenFunction(pixel, result, cBufferNonEmpty); vstd::StringBuilder retName; auto retType = pixel.return_type(); GetTypeName(*retType, retName, Usage::READ); diff --git a/src/backends/dx/DXApi/LCDevice.cpp b/src/backends/dx/DXApi/LCDevice.cpp index 024f5e6e6..4b60ae703 100644 --- a/src/backends/dx/DXApi/LCDevice.cpp +++ b/src/backends/dx/DXApi/LCDevice.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "ext.h" #include "../../common/hlsl/hlsl_codegen.h" #include @@ -97,6 +98,14 @@ LCDevice::LCDevice(Context &&ctx, DeviceConfig const *settings) [](DeviceExtension *ext) { delete static_cast(ext); }); + exts.try_emplace( + DXHDRExt::name, + [](LCDevice *device) -> DeviceExtension * { + return new DXHDRExtImpl(device); + }, + [](DeviceExtension *ext) { + delete static_cast(ext); + }); #ifdef LCDX_ENABLE_CUDA exts.try_emplace( DxCudaInterop::name, @@ -305,7 +314,7 @@ ShaderCreationInfo LCDevice::create_shader(const ShaderOption &option, Function mask |= (1 << 1); } // use default control flow - constexpr uint compiler_version = 202403u; // dxc version at march 2024 + constexpr uint compiler_version = 202403u;// dxc version at march 2024 mask |= (1 << 2); mask |= compiler_version << 3u; auto code = hlsl::CodegenUtility{}.Codegen(kernel, option.native_include, mask, false); @@ -465,7 +474,7 @@ SwapchainCreationInfo LCDevice::create_swapchain(const SwapchainOption &option, reinterpret_cast(option.window), option.size.x, option.size.y, - option.wants_hdr, + option.wants_hdr ? DXGI_FORMAT_R16G16B16A16_FLOAT : DXGI_FORMAT_R8G8B8A8_UNORM, option.wants_vsync, option.back_buffer_count); info.handle = resource_to_handle(res); diff --git a/src/backends/dx/DXApi/LCSwapChain.cpp b/src/backends/dx/DXApi/LCSwapChain.cpp index 3ae0036f5..7df10477b 100644 --- a/src/backends/dx/DXApi/LCSwapChain.cpp +++ b/src/backends/dx/DXApi/LCSwapChain.cpp @@ -10,10 +10,11 @@ LCSwapChain::LCSwapChain( HWND windowHandle, uint width, uint height, - bool allowHDR, + DXGI_FORMAT format, bool vsync, uint backBufferCount) : Resource(device), vsync(vsync) { + this->format = format; auto frameCount = backBufferCount + 1; vstd::push_back_func( m_renderTargets, @@ -23,7 +24,7 @@ LCSwapChain::LCSwapChain( swapChainDesc.BufferCount = frameCount; swapChainDesc.Width = width; swapChainDesc.Height = height; - swapChainDesc.Format = allowHDR ? DXGI_FORMAT_R16G16B16A16_FLOAT : DXGI_FORMAT_R8G8B8A8_UNORM; + swapChainDesc.Format = format; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; if (!vsync) @@ -39,7 +40,7 @@ LCSwapChain::LCSwapChain( nullptr, nullptr, &localSwap)); - swapChain = DxPtr(static_cast(localSwap), true); + swapChain = DxPtr(static_cast(localSwap), true); } for (uint32_t n = 0; n < frameCount; n++) { ThrowIfFailed(swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n].rt))); @@ -50,7 +51,7 @@ LCSwapChain::LCSwapChain( LCSwapChain::LCSwapChain( PixelStorage &storage, Device *device, - IDXGISwapChain3 *swapChain, + IDXGISwapChain4 *swapChain, bool vsync) : Resource(device), swapChain(swapChain, false), diff --git a/src/backends/dx/DXApi/LCSwapChain.h b/src/backends/dx/DXApi/LCSwapChain.h index 73072b637..58f62e144 100644 --- a/src/backends/dx/DXApi/LCSwapChain.h +++ b/src/backends/dx/DXApi/LCSwapChain.h @@ -9,8 +9,9 @@ namespace lc::dx { class LCSwapChain : public Resource { public: vstd::vector m_renderTargets; - DxPtr swapChain; + DxPtr swapChain; uint64 frameIndex = 0; + DXGI_FORMAT format; bool vsync; Tag GetTag() const override { return Tag::SwapChain; } LCSwapChain( @@ -20,13 +21,13 @@ class LCSwapChain : public Resource { HWND windowHandle, uint width, uint height, - bool allowHDR, + DXGI_FORMAT format, bool vsync, uint backBufferCount); LCSwapChain( PixelStorage& storage, Device* device, - IDXGISwapChain3* swapChain, + IDXGISwapChain4* swapChain, bool vsync); }; }// namespace lc::dx diff --git a/src/backends/dx/DXApi/dx_hdr_ext.cpp b/src/backends/dx/DXApi/dx_hdr_ext.cpp new file mode 100644 index 000000000..1e2f28b21 --- /dev/null +++ b/src/backends/dx/DXApi/dx_hdr_ext.cpp @@ -0,0 +1,171 @@ +#include +#include +#include +#include +#include +#include +namespace lc::dx { +using namespace luisa::compute; +namespace dx_hdr_ext_detail { + +DXHDRExt::DisplayCurve EnsureSwapChainColorSpace( + IDXGISwapChain4 *swapChain, + DXGI_COLOR_SPACE_TYPE ¤tSwapChainColorSpace, + DXHDRExt::SwapChainBitDepth swapChainBitDepth, + bool enableST2084) { + DXHDRExt::DisplayCurve result{DXHDRExt::DisplayCurve::None}; + DXGI_COLOR_SPACE_TYPE colorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + switch (swapChainBitDepth) { + case DXHDRExt::SwapChainBitDepth::_8: + result = DXHDRExt::DisplayCurve::sRGB; + break; + + case DXHDRExt::SwapChainBitDepth::_10: + colorSpace = enableST2084 ? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 : DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + result = enableST2084 ? DXHDRExt::DisplayCurve::ST2084 : DXHDRExt::DisplayCurve::sRGB; + break; + + case DXHDRExt::SwapChainBitDepth::_16: + colorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709; + result = DXHDRExt::DisplayCurve::None; + break; + } + + if (currentSwapChainColorSpace != colorSpace) { + UINT colorSpaceSupport = 0; + if (SUCCEEDED(swapChain->CheckColorSpaceSupport(colorSpace, &colorSpaceSupport)) && + ((colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) == DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)) { + ThrowIfFailed(swapChain->SetColorSpace1(colorSpace)); + currentSwapChainColorSpace = colorSpace; + } + } + return result; +} +DXHDRExt::DisplayChromaticities SetHDRMetaData( + DXGI_COLOR_SPACE_TYPE &colorSpace, + LCSwapChain *swapchain, + bool hdr_support, + float MaxOutputNits /*=1000.0f*/, + float MinOutputNits /*=0.001f*/, + float MaxCLL /*=2000.0f*/, + float MaxFALL /*=500.0f*/, + const DXHDRExt::DisplayChromaticities *Chroma) { + if (!swapchain) { + return {}; + } + + // Clean the hdr metadata if the display doesn't support HDR + if (!hdr_support) { + ThrowIfFailed(swapchain->swapChain->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_NONE, 0, nullptr)); + return {}; + } + + static const DXHDRExt::DisplayChromaticities DisplayChromaticityList[] = + { + {0.64000f, 0.33000f, 0.30000f, 0.60000f, 0.15000f, 0.06000f, 0.31270f, 0.32900f},// Display Gamut Rec709 + {0.70800f, 0.29200f, 0.17000f, 0.79700f, 0.13100f, 0.04600f, 0.31270f, 0.32900f},// Display Gamut Rec2020 + }; + + // Select the chromaticity based on HDR format of the DWM. + DXHDRExt::SwapChainBitDepth hitDepth; + switch (swapchain->format) { + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + hitDepth = DXHDRExt::SwapChainBitDepth::_10; + break; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + hitDepth = DXHDRExt::SwapChainBitDepth::_16; + break; + default: + hitDepth = DXHDRExt::SwapChainBitDepth::_8; + break; + } + + EnsureSwapChainColorSpace(swapchain->swapChain, colorSpace, hitDepth, hdr_support); + int selectedChroma = 0; + if (swapchain->format == DXGI_FORMAT_R16G16B16A16_FLOAT && colorSpace == DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709) { + selectedChroma = 0; + } else if (hitDepth == DXHDRExt::SwapChainBitDepth::_10 && colorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) { + selectedChroma = 1; + } else { + // Reset the metadata since this is not a supported HDR format. + ThrowIfFailed(swapchain->swapChain->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_NONE, 0, nullptr)); + return {}; + } + + // Set HDR meta data + if (!Chroma) + Chroma = &DisplayChromaticityList[selectedChroma]; + DXGI_HDR_METADATA_HDR10 HDR10MetaData = {}; + HDR10MetaData.RedPrimary[0] = static_cast(Chroma->RedX * 50000.0f); + HDR10MetaData.RedPrimary[1] = static_cast(Chroma->RedY * 50000.0f); + HDR10MetaData.GreenPrimary[0] = static_cast(Chroma->GreenX * 50000.0f); + HDR10MetaData.GreenPrimary[1] = static_cast(Chroma->GreenY * 50000.0f); + HDR10MetaData.BluePrimary[0] = static_cast(Chroma->BlueX * 50000.0f); + HDR10MetaData.BluePrimary[1] = static_cast(Chroma->BlueY * 50000.0f); + HDR10MetaData.WhitePoint[0] = static_cast(Chroma->WhiteX * 50000.0f); + HDR10MetaData.WhitePoint[1] = static_cast(Chroma->WhiteY * 50000.0f); + HDR10MetaData.MaxMasteringLuminance = static_cast(MaxOutputNits * 10000.0f); + HDR10MetaData.MinMasteringLuminance = static_cast(MinOutputNits * 10000.0f); + HDR10MetaData.MaxContentLightLevel = static_cast(MaxCLL); + HDR10MetaData.MaxFrameAverageLightLevel = static_cast(MaxFALL); + ThrowIfFailed(swapchain->swapChain->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_HDR10, sizeof(DXGI_HDR_METADATA_HDR10), &HDR10MetaData)); + return *Chroma; +} +}// namespace dx_hdr_ext_detail +DXHDRExtImpl::DXHDRExtImpl(LCDevice *lc_device) : _lc_device(lc_device) {} +DXHDRExtImpl::~DXHDRExtImpl() = default; + +SwapchainCreationInfo DXHDRExtImpl::create_swapchain( + const DXSwapchainOption &option, + uint64_t stream_handle) noexcept { + auto queue = reinterpret_cast(stream_handle); + if (queue->Tag() != CmdQueueTag::MainCmd) [[unlikely]] { + LUISA_ERROR("swapchain not allowed in Direct-Storage."); + } + SwapchainCreationInfo info; + auto res = new LCSwapChain( + &(_lc_device->nativeDevice), + &reinterpret_cast(stream_handle)->queue, + _lc_device->nativeDevice.defaultAllocator.get(), + reinterpret_cast(option.window), + option.size.x, + option.size.y, + static_cast(TextureBase::ToGFXFormat(pixel_storage_to_format(option.storage))), + option.wants_vsync, + option.back_buffer_count); + info.handle = resource_to_handle(res); + info.native_handle = res->swapChain.Get(); + info.storage = option.storage; + return info; +} + +auto DXHDRExtImpl::set_hdr_meta_data( + uint64_t swapchain_handle, + float max_output_nits, + float min_output_nits, + float max_cll, + float max_fall, + const DXHDRExt::DisplayChromaticities *custom_chroma) noexcept -> Meta { + DXGI_COLOR_SPACE_TYPE color_space = DXGI_COLOR_SPACE_CUSTOM; + auto chroma = dx_hdr_ext_detail::SetHDRMetaData( + color_space, + reinterpret_cast(swapchain_handle), + true, + max_output_nits, + min_output_nits, + max_cll, + max_fall, + custom_chroma); + return { + static_cast(color_space), + chroma}; +} +}// namespace lc::dx \ No newline at end of file diff --git a/src/backends/dx/DXApi/dx_hdr_ext.hpp b/src/backends/dx/DXApi/dx_hdr_ext.hpp new file mode 100644 index 000000000..1b77853ca --- /dev/null +++ b/src/backends/dx/DXApi/dx_hdr_ext.hpp @@ -0,0 +1,21 @@ +#pragma once +#include +#include +namespace lc::dx { +class DXHDRExtImpl : public luisa::compute::DXHDRExt { + LCDevice *_lc_device; +public: + DXHDRExtImpl(LCDevice *lc_device); + ~DXHDRExtImpl(); + SwapchainCreationInfo create_swapchain( + const DXSwapchainOption &option, + uint64_t stream_handle) noexcept override; + Meta set_hdr_meta_data( + uint64_t swapchain_handle, + float max_output_nits = 1000.0f, + float min_output_nits = 0.001f, + float max_cll = 2000.0f, + float max_fall = 500.0f, + const DXHDRExt::DisplayChromaticities *custom_chroma = nullptr) noexcept override; +}; +}// namespace lc::dx \ No newline at end of file diff --git a/src/backends/dx/DXApi/ext.cpp b/src/backends/dx/DXApi/ext.cpp index b3d375c35..c58b983dc 100644 --- a/src/backends/dx/DXApi/ext.cpp +++ b/src/backends/dx/DXApi/ext.cpp @@ -149,7 +149,7 @@ SwapchainCreationInfo DxNativeResourceExt::register_external_swapchain( auto res = new LCSwapChain( info.storage, dx_device, - reinterpret_cast(swapchain_ptr), + reinterpret_cast(swapchain_ptr), vsync); info.handle = reinterpret_cast(res); info.native_handle = swapchain_ptr; diff --git a/src/backends/dx/DXRuntime/CommandAllocator.cpp b/src/backends/dx/DXRuntime/CommandAllocator.cpp index 66d49001e..b5ff1b9e4 100644 --- a/src/backends/dx/DXRuntime/CommandAllocator.cpp +++ b/src/backends/dx/DXRuntime/CommandAllocator.cpp @@ -82,7 +82,7 @@ void CommandAllocator::Execute( } } } -void CommandAllocator::ExecuteAndPresent(CommandQueue *queue, ID3D12Fence *fence, uint64 fenceIndex, IDXGISwapChain3 *swapchain, bool vsync) { +void CommandAllocator::ExecuteAndPresent(CommandQueue *queue, ID3D12Fence *fence, uint64 fenceIndex, IDXGISwapChain4 *swapchain, bool vsync) { auto present = [&]() { if (vsync) { ThrowIfFailed(swapchain->Present(1, 0)); diff --git a/src/backends/dx/DXRuntime/CommandAllocator.h b/src/backends/dx/DXRuntime/CommandAllocator.h index ed7a43fcc..5efc05f6e 100644 --- a/src/backends/dx/DXRuntime/CommandAllocator.h +++ b/src/backends/dx/DXRuntime/CommandAllocator.h @@ -81,7 +81,7 @@ class CommandAllocator final : public vstd::IOperatorNewBase { ~CommandAllocator(); CommandBuffer *GetBuffer() const; void Execute(CommandQueue *queue, ID3D12Fence *fence, uint64 fenceIndex); - void ExecuteAndPresent(CommandQueue *queue, ID3D12Fence *fence, uint64 fenceIndex, IDXGISwapChain3 *swapchain, bool vsync); + void ExecuteAndPresent(CommandQueue *queue, ID3D12Fence *fence, uint64 fenceIndex, IDXGISwapChain4 *swapchain, bool vsync); void Complete(CommandQueue *queue, ID3D12Fence *fence, uint64 fenceIndex); DefaultBuffer const *AllocateScratchBuffer(size_t targetSize); BufferView GetTempReadbackBuffer(uint64 size, size_t align = 0); diff --git a/src/backends/dx/DXRuntime/CommandQueue.cpp b/src/backends/dx/DXRuntime/CommandQueue.cpp index 946e99842..fd5b07dd1 100644 --- a/src/backends/dx/DXRuntime/CommandQueue.cpp +++ b/src/backends/dx/DXRuntime/CommandQueue.cpp @@ -187,7 +187,7 @@ void CommandQueue::ExecuteEmptyCallbacks(AllocatorPtr &&alloc, vstd::vectorExecuteAndPresent(this, cmdFence.Get(), curFrame, swapChain, vsync); mtx.lock(); diff --git a/src/backends/dx/DXRuntime/CommandQueue.h b/src/backends/dx/DXRuntime/CommandQueue.h index e6b7f40e6..dabb4ab3f 100644 --- a/src/backends/dx/DXRuntime/CommandQueue.h +++ b/src/backends/dx/DXRuntime/CommandQueue.h @@ -61,7 +61,7 @@ class CommandQueue : vstd::IOperatorNewBase { void ExecuteCallbacks(AllocatorPtr &&alloc, vstd::vector> &&callbacks); void ExecuteEmpty(AllocatorPtr &&alloc); void ExecuteEmptyCallbacks(AllocatorPtr &&alloc, vstd::vector> &&callbacks); - void ExecuteAndPresent(AllocatorPtr &&alloc, IDXGISwapChain3 *swapChain, bool vsync); + void ExecuteAndPresent(AllocatorPtr &&alloc, IDXGISwapChain4 *swapChain, bool vsync); void Complete(uint64 fence); void Complete(); void ForceSync( diff --git a/src/backends/dx/DXRuntime/Device.cpp b/src/backends/dx/DXRuntime/Device.cpp index ca40878ce..507d6b5f2 100644 --- a/src/backends/dx/DXRuntime/Device.cpp +++ b/src/backends/dx/DXRuntime/Device.cpp @@ -240,7 +240,6 @@ Device::Device(Context &&ctx, DeviceConfig const *settings) D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 16, true)); - hdr.create(dxgiFactory.Get(), adapter.Get()); auto samplers = GlobalSamplers::GetSamplers(); for (auto i : vstd::range(samplers.size())) { samplerHeap->CreateSampler( diff --git a/src/backends/dx/DXRuntime/Device.h b/src/backends/dx/DXRuntime/Device.h index 81f98c886..b58d398ab 100644 --- a/src/backends/dx/DXRuntime/Device.h +++ b/src/backends/dx/DXRuntime/Device.h @@ -9,7 +9,6 @@ #include #include #include "../../common/default_binary_io.h" -#include "HDR.h" #include namespace luisa { @@ -82,7 +81,6 @@ class Device { vstd::unique_ptr globalHeap; vstd::unique_ptr samplerHeap; - vstd::optional hdr; LazyLoadShader setBindlessKernel; LazyLoadShader setAccelKernel; diff --git a/src/backends/dx/DXRuntime/HDR.cpp b/src/backends/dx/DXRuntime/HDR.cpp deleted file mode 100644 index aac011978..000000000 --- a/src/backends/dx/DXRuntime/HDR.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "HDR.h" -#include -namespace lc::dx { -using Microsoft::WRL::ComPtr; -inline int ComputeIntersectionArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) { - return std::max(0, std::min(ax2, bx2) - std::max(ax1, bx1)) * std::max(0, std::min(ay2, by2) - std::max(ay1, by1)); -} -HDR::HDR(IDXGIFactory2 *factory, IDXGIAdapter1 *adapter) { - UINT i = 0; - ComPtr currentOutput; - // float bestIntersectArea = -1; - supportHdr = false; - while (adapter->EnumOutputs(i, ¤tOutput) != DXGI_ERROR_NOT_FOUND) { - ComPtr output6; - ThrowIfFailed(currentOutput.As(&output6)); - - DXGI_OUTPUT_DESC1 desc1; - ThrowIfFailed(output6->GetDesc1(&desc1)); - - if (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) { - supportHdr = true; - break; - } - ++i; - } -} -std::pair HDR::CheckSwapChainSupport(IDXGISwapChain3 *swapChain) { - DXGI_COLOR_SPACE_TYPE currentColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; - HDRSupport result = HDRSupport::None; - auto CheckSupport = [&](DXGI_COLOR_SPACE_TYPE colorSpace, HDRSupport support) { - UINT colorSpaceSupport = 0; - if (SUCCEEDED(swapChain->CheckColorSpaceSupport(colorSpace, &colorSpaceSupport)) && - ((colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) == DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)) { - currentColorSpace = colorSpace; - result = support; - return true; - } - return false; - }; - if (supportHdr) { - if (CheckSupport(DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, HDRSupport::F16)) return {result, currentColorSpace}; - if (CheckSupport(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, HDRSupport::RGB10)) return {result, currentColorSpace}; - } - CheckSupport(supportHdr ? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 : DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, HDRSupport::None); - return {result, currentColorSpace}; -} -HDR::~HDR() { -} -}// namespace lc::dx diff --git a/src/backends/dx/DXRuntime/HDR.h b/src/backends/dx/DXRuntime/HDR.h deleted file mode 100644 index 81c06a38a..000000000 --- a/src/backends/dx/DXRuntime/HDR.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include -#include -namespace lc::dx { -class HDR { -private: - bool supportHdr; - -public: - enum class HDRSupport : uint { - None, - RGB10,// DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 - F16, // DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 - }; - bool SupportHdr() const { return supportHdr; } - HDR(IDXGIFactory2 *factory, IDXGIAdapter1 *adapter); - std::pair CheckSwapChainSupport(IDXGISwapChain3* swapChain); - ~HDR(); -}; -}// namespace lc::dx diff --git a/src/backends/dx/Shader/RasterShader.cpp b/src/backends/dx/Shader/RasterShader.cpp index b0113921c..0cfb22028 100644 --- a/src/backends/dx/Shader/RasterShader.cpp +++ b/src/backends/dx/Shader/RasterShader.cpp @@ -7,7 +7,14 @@ #include namespace lc::dx { namespace RasterShaderDetail { -static constexpr bool PRINT_CODE = false; +static const bool PRINT_CODE = ([] { + // read env LUISA_DUMP_SOURCE + auto env = std::getenv("LUISA_DUMP_SOURCE"); + if (env == nullptr) { + return false; + } + return std::string_view{env} == "1"; +})(); static vstd::vector GetKernelArgs(Function vertexKernel, Function pixelKernel) { if (vertexKernel.builder() == nullptr || pixelKernel.builder() == nullptr) { return {}; @@ -278,7 +285,7 @@ RasterShader *RasterShader::CompileRaster( if (str.useBufferBindless) bdlsBufferCount++; if (str.useTex2DBindless) bdlsBufferCount++; if (str.useTex3DBindless) bdlsBufferCount++; - if constexpr (RasterShaderDetail::PRINT_CODE) { + if (RasterShaderDetail::PRINT_CODE) { auto f = fopen("hlsl_output.hlsl", "wb"); fwrite(str.result.data(), str.result.size(), 1, f); fclose(f); @@ -349,7 +356,7 @@ void RasterShader::SaveRaster( Function pixelKernel, uint shaderModel, bool enableUnsafeMath) { - if constexpr (RasterShaderDetail::PRINT_CODE) { + if (RasterShaderDetail::PRINT_CODE) { auto f = fopen("hlsl_output.hlsl", "ab"); fwrite(str.result.data(), str.result.size(), 1, f); fclose(f); diff --git a/src/core/dynamic_module.cpp b/src/core/dynamic_module.cpp index af3bd5682..8d6a9347b 100644 --- a/src/core/dynamic_module.cpp +++ b/src/core/dynamic_module.cpp @@ -34,7 +34,7 @@ void DynamicModule::dispose() noexcept { } [[nodiscard]] static auto &dynamic_module_search_paths() noexcept { - static luisa::vector> paths; + static luisa::vector> paths; return paths; } @@ -45,21 +45,27 @@ void DynamicModule::dispose() noexcept { } #endif -void DynamicModule::add_search_path(const std::filesystem::path &path) noexcept { - std::lock_guard lock{dynamic_module_search_path_mutex()}; - auto canonical_path = std::filesystem::canonical(path); +void DynamicModule::add_search_path(const luisa::filesystem::path &path) noexcept { + std::lock_guard lock { dynamic_module_search_path_mutex() }; + auto canonical_path = luisa::filesystem::canonical(path); auto &&paths = dynamic_module_search_paths(); - if (auto iter = std::find_if(paths.begin(), paths.end(), [&canonical_path](auto &&p) noexcept { - return p.first == canonical_path; - }); - iter != paths.end()) { + if ( + auto iter = std::find_if( + paths.begin(), + paths.end(), + [&canonical_path](auto &&p) noexcept { + return p.first == canonical_path; + } + ); + iter != paths.end() + ) { iter->second++; } else { #ifdef LUISA_PLATFORM_WINDOWS auto &&cookies = dynamic_module_search_path_cookies(); cookies.emplace_back(AddDllDirectory(canonical_path.c_str())); #endif - paths.emplace_back(std::move(canonical_path), 0u); + paths.emplace_back(std::move(canonical_path), 0); } } @@ -106,17 +112,21 @@ DynamicModule DynamicModule::load(std::string_view name) noexcept { return DynamicModule{nullptr}; } -DynamicModule DynamicModule::load(const std::filesystem::path &folder, std::string_view name) noexcept { +DynamicModule DynamicModule::load( + const luisa::filesystem::path &folder, + luisa::string_view name +) noexcept { Clock clock; auto p = folder / dynamic_module_name(name); if (auto handle = dynamic_module_load(p)) { LUISA_INFO( "Loaded dynamic module '{}' in {} ms.", - to_string(p), clock.toc()); - return DynamicModule{handle}; + to_string(p), clock.toc() + ); + return DynamicModule { handle }; } - return DynamicModule{nullptr}; -} -}// namespace luisa + return DynamicModule { nullptr }; +} +} // namespace luisa end diff --git a/src/core/platform.cpp b/src/core/platform.cpp index 3b3f4678b..fc8cff355 100644 --- a/src/core/platform.cpp +++ b/src/core/platform.cpp @@ -228,8 +228,10 @@ void *dynamic_module_load(const luisa::filesystem::path &path) noexcept { } LUISA_WARNING_WITH_LOCATION( "Failed to load dynamic module '{}', reason: {}.", - luisa::to_string(p), dlerror()); + luisa::to_string(p), dlerror() + ); } + return nullptr; } diff --git a/src/ext/EASTL b/src/ext/EASTL index c7357ae59..1bb84e7a7 160000 --- a/src/ext/EASTL +++ b/src/ext/EASTL @@ -1 +1 @@ -Subproject commit c7357ae591d9c7bd38598256c42d850f0e43be39 +Subproject commit 1bb84e7a7d7b984b7244a6a049c1df6b26f15186 diff --git a/src/ext/glfw b/src/ext/glfw index b35641f4a..21fea0116 160000 --- a/src/ext/glfw +++ b/src/ext/glfw @@ -1 +1 @@ -Subproject commit b35641f4a3c62aa86a0b3c983d163bc0fe36026d +Subproject commit 21fea01161e0d6b70c0c5c1f52dc8e7a7df14a50 diff --git a/src/ext/imgui b/src/ext/imgui index 368123ab0..947aa9c97 160000 --- a/src/ext/imgui +++ b/src/ext/imgui @@ -1 +1 @@ -Subproject commit 368123ab06b2b573d585e52f84cd782c5c006697 +Subproject commit 947aa9c9722bd6ff740dd757da609ff41f4d3ba3 diff --git a/src/ext/magic_enum b/src/ext/magic_enum index a72a0536c..1a1824df7 160000 --- a/src/ext/magic_enum +++ b/src/ext/magic_enum @@ -1 +1 @@ -Subproject commit a72a0536c716fdef4f029fb43e1fd7e7b3d9ac9b +Subproject commit 1a1824df7ac798177a521eed952720681b0bf482 diff --git a/src/ext/stb/stb b/src/ext/stb/stb index 0dd01c26e..5c205738c 160000 --- a/src/ext/stb/stb +++ b/src/ext/stb/stb @@ -1 +1 @@ -Subproject commit 0dd01c26ef47750512cdc1830581480c25a19f1d +Subproject commit 5c205738c191bcb0abc65c4febfa9bd25ff35234 diff --git a/src/ext/xxHash b/src/ext/xxHash index dd11140c2..2bf8313b9 160000 --- a/src/ext/xxHash +++ b/src/ext/xxHash @@ -1 +1 @@ -Subproject commit dd11140c2dc5d53a3c0a949d67af7f40f546878e +Subproject commit 2bf8313b934633b2a5b7e8fd239645b85e10c852 diff --git a/src/runtime/context.cpp b/src/runtime/context.cpp index 0858172b9..76f11e984 100644 --- a/src/runtime/context.cpp +++ b/src/runtime/context.cpp @@ -61,118 +61,168 @@ namespace detail { class ContextImpl { public: - std::filesystem::path runtime_directory; + luisa::filesystem::path runtime_directory; luisa::unordered_map> loaded_backends; luisa::vector installed_backends; ValidationLayer validation_layer; - luisa::unordered_map> runtime_subdir_paths; + luisa::unordered_map> runtime_subdir_paths; std::mutex runtime_subdir_mutex; std::mutex module_mutex; [[nodiscard]] const BackendModule &load_backend(const luisa::string &backend_name) noexcept { - if (std::find(installed_backends.cbegin(), - installed_backends.cend(), - backend_name) == installed_backends.cend()) { + if ( + std::find( + installed_backends.cbegin(), + installed_backends.cend(), + backend_name + ) == installed_backends.cend() + ) { LUISA_ERROR_WITH_LOCATION("Backend '{}' is not installed.", backend_name); } - std::scoped_lock lock{module_mutex}; - if (auto iter = loaded_backends.find(backend_name); - iter != loaded_backends.cend()) { return *iter->second; } - BackendModule m{.module = DynamicModule::load( - runtime_directory, - luisa::format("lc-backend-{}", backend_name))}; + + std::scoped_lock lock { module_mutex }; + if ( + auto iter = loaded_backends.find(backend_name); + iter != loaded_backends.cend() + ) { + return *iter->second; + } + BackendModule m { + .module = DynamicModule::load( + runtime_directory, + luisa::format("lc-backend-{}", backend_name) + ) + }; LUISA_ASSERT(m.module, "Failed to load backend '{}'.", backend_name); m.creator = m.module.function("create"); m.deleter = m.module.function("destroy"); m.backend_device_names = m.module.function("backend_device_names"); - auto pm = loaded_backends - .emplace(backend_name, luisa::make_unique(std::move(m))) - .first->second.get(); + auto pm = loaded_backends.emplace( + backend_name, + luisa::make_unique(std::move(m)) + ).first->second.get(); + return *pm; } [[nodiscard]] const ValidationLayer &load_validation_layer() noexcept { - std::scoped_lock lock{module_mutex}; + std::scoped_lock lock { module_mutex }; if (!validation_layer.module) { validation_layer.module = DynamicModule::load(runtime_directory, "lc-validation-layer"); validation_layer.creator = validation_layer.module.function("create"); validation_layer.deleter = validation_layer.module.function("destroy"); } + return validation_layer; } explicit ContextImpl(luisa::string_view program_path) noexcept { - std::filesystem::path program{program_path}; + using namespace std::string_view_literals; + + luisa::filesystem::path program { program_path }; + LUISA_INFO( + "Created context for program '{}'.", + luisa::to_string(program.filename()) + ); + { - auto cp = std::filesystem::canonical(program); - if (std::filesystem::is_directory(cp)) { + auto cp = luisa::filesystem::canonical(program); + if (luisa::filesystem::is_directory(cp)) { runtime_directory = std::move(cp); } else { - runtime_directory = std::filesystem::canonical(cp.parent_path()); + runtime_directory = luisa::filesystem::canonical(cp.parent_path()); } + LUISA_INFO( + "Runtime directory: {}.", + luisa::to_string(runtime_directory) + ); + DynamicModule::add_search_path(runtime_directory); } - LUISA_INFO("Created context for program '{}'.", to_string(program.filename())); - LUISA_INFO("Runtime directory: {}.", to_string(runtime_directory)); - DynamicModule::add_search_path(runtime_directory); - for (auto &&p : std::filesystem::directory_iterator{runtime_directory}) { - if (auto &&path = p.path(); - p.is_regular_file() && - (path.extension() == ".so" || - path.extension() == ".dll" || - path.extension() == ".dylib")) { - using namespace std::string_view_literals; - constexpr std::array possible_prefixes{ - "lc-backend-"sv, - // Make Mingw happy - "liblc-backend-"sv}; - auto filename = to_string(path.stem()); + + const auto extension_so = luisa::filesystem::path(".so"); + const auto extension_dll = luisa::filesystem::path(".dll"); + const auto extension_dylib = luisa::filesystem::path(".dylib"); + constexpr std::array possible_prefixes { + "lc-backend-"sv, + "liblc-backend-"sv // Make Mingw happy + }; + for (auto &&p : luisa::filesystem::directory_iterator{runtime_directory}) { + auto &&path = p.path(); + auto p_is_regular_file = p.is_regular_file(); + const auto path_extension = path.extension(); + + if ( + p_is_regular_file && ( + path_extension == extension_so || + path_extension == extension_dll || + path_extension == extension_dylib + ) + ) { + auto filename = luisa::to_string(path.stem()); for (auto prefix : possible_prefixes) { if (filename.starts_with(prefix)) { - auto name = filename.substr(prefix.size()); - for (auto &c : name) { c = static_cast(std::tolower(c)); } - LUISA_VERBOSE_WITH_LOCATION("Found backend: {}.", name); - installed_backends.emplace_back(std::move(name)); + auto backend_name = filename.substr(prefix.size()); + for (auto &c : backend_name) { + c = static_cast(std::tolower(c)); + } + LUISA_VERBOSE_WITH_LOCATION("Found backend: {}.", backend_name); + installed_backends.emplace_back(std::move(backend_name)); break; } } } } - luisa::sort(installed_backends.begin(), installed_backends.end()); + luisa::sort( + installed_backends.begin(), + installed_backends.end() + ); installed_backends.erase( - std::unique(installed_backends.begin(), installed_backends.end()), - installed_backends.end()); + std::unique( + installed_backends.begin(), + installed_backends.end() + ), + installed_backends.end() + ); } + ~ContextImpl() noexcept { DynamicModule::remove_search_path(runtime_directory); } }; -}// namespace detail +} // namespace detail end + Context::Context(string_view program_path) noexcept - : _impl{luisa::make_shared(program_path)} {} + : _impl{luisa::make_shared(program_path)} +{} -Device Context::create_device(luisa::string_view backend_name_in, const DeviceConfig *settings, bool enable_validation) noexcept { - luisa::string backend_name{backend_name_in}; - for (auto &c : backend_name) { c = static_cast(std::tolower(c)); } +Device Context::create_device( + luisa::string_view backend_name_in, + const DeviceConfig *settings, + bool enable_validation +) noexcept { + luisa::string backend_name { backend_name_in }; auto &&m = _impl->load_backend(backend_name); auto interface = m.creator(Context{_impl}, settings); interface->_backend_name = std::move(backend_name); - auto handle = Device::Handle{ + auto handle = Device::Handle { interface, [impl = _impl, deleter = m.deleter](auto p) noexcept { deleter(p); - }}; + } + }; if (enable_validation) { auto &validation_layer = _impl->load_validation_layer(); - auto layer_handle = Device::Handle{ + auto layer_handle = Device::Handle { validation_layer.creator(Context{_impl}, std::move(handle)), [impl = _impl](auto layer) noexcept { impl->validation_layer.deleter(layer); - }}; - return Device{std::move(layer_handle)}; + } + }; + return Device { std::move(layer_handle) }; } else { - return Device{std::move(handle)}; + return Device { std::move(handle) }; } } @@ -216,7 +266,7 @@ const luisa::filesystem::path &Context::create_runtime_subdir(luisa::string_view "Failed to create runtime sub-directory '{}': {}.", to_string(dir), ec.message()); } - return luisa::make_unique(std::move(dir)); + return luisa::make_unique(std::move(dir)); })); return *iter.first->second; }