diff --git a/.gitmodules b/.gitmodules index 3febc1839..f99368d97 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "external/vulkan-headers"] path = external/vulkan-headers url = https://github.com/KhronosGroup/Vulkan-Headers +[submodule "external/gli"] + path = external/gli + url = https://github.com/g-truc/gli.git diff --git a/Source/Falcor/CMakeLists.txt b/Source/Falcor/CMakeLists.txt index d1e34a015..b975c2605 100644 --- a/Source/Falcor/CMakeLists.txt +++ b/Source/Falcor/CMakeLists.txt @@ -850,7 +850,7 @@ target_link_libraries(Falcor PRIVATE git_version FreeImage assimp ffmpeg OpenEXR OpenVDB lz4 zlib pugixml - glfw mikktspace nvtt + gli glfw mikktspace nvtt $<$:d3d12> $<$:agility-sdk> $<$:nvapi> diff --git a/Source/Falcor/Core/API/Texture.cpp b/Source/Falcor/Core/API/Texture.cpp index 3410dd822..e93198ece 100644 --- a/Source/Falcor/Core/API/Texture.cpp +++ b/Source/Falcor/Core/API/Texture.cpp @@ -39,7 +39,9 @@ #include "Utils/Image/ImageIO.h" #include "Utils/Scripting/ScriptBindings.h" #include "RenderGraph/BasePasses/FullScreenPass.h" +#include "NativeFormats.h" +#include #include #include @@ -441,16 +443,41 @@ void Texture::captureToFile( Bitmap::ExportFlags exportFlags ) { + RenderContext* pContext = mpDevice->getRenderContext(); + if (format == Bitmap::FileFormat::DdsFile) { - throw RuntimeError("Texture::captureToFile does not yet support saving to DDS."); + gli::dx dxc; + auto dxgiFormat = getDxgiFormat(mFormat); + auto gliFormat = dxc.find(gli::dx::D3DFMT_DX10, gli::dx::dxgiFormat{ gli::dx::dxgi_format_dds(dxgiFormat) }); + + if (mType != Type::Texture2D) throw RuntimeError("Texture::captureToFile dds files must be texture 2d"); + gli::texture2d_array gliTex = gli::texture2d_array( + gliFormat, + gli::extent2d(mWidth, mHeight), + mArraySize, mMipLevels); + + // transfer data + for (uint32_t level = 0; level < mMipLevels; ++level) + { + const auto size = gliTex.size(level); + for (uint32_t layer = 0; layer < mArraySize; ++layer) + { + auto subresourceIndex = getSubresourceIndex(layer, mipLevel); + auto srcData = pContext->readTextureSubresource(this, subresourceIndex); + auto dstData = gliTex.data(layer, 0, level); + assert(size <= srcData.size()); + memcpy(dstData, srcData.data(), size); + } + } + + gli::save_dds(gliTex, path.string()); + return; } if (mType != Type::Texture2D) throw RuntimeError("Texture::captureToFile only supported for 2D textures."); - RenderContext* pContext = mpDevice->getRenderContext(); - // Handle the special case where we have an HDR texture with less then 3 channels. FormatType type = getFormatType(mFormat); uint32_t channels = getFormatChannelCount(mFormat); diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 7e7e9db36..4ab27bfd9 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -41,6 +41,11 @@ add_subdirectory(glfw) message(STATUS "Configure glm") add_subdirectory(glm) +# gli +message(STATUS "Configure gli") +set(GLI_TEST_ENABLE OFF) +add_subdirectory(gli) + # imgui add_library(imgui INTERFACE) target_include_directories(imgui INTERFACE imgui) diff --git a/external/gli b/external/gli new file mode 160000 index 000000000..779b99ac6 --- /dev/null +++ b/external/gli @@ -0,0 +1 @@ +Subproject commit 779b99ac6656e4d30c3b24e96e0136a59649a869