/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "ImageLoaderDds.hpp" #include namespace OpenVulkano::Image { std::unique_ptr ImageLoaderDds::loadFromFile(const std::string& filePath) { dds::Image image; if (dds::readFile(filePath, &image) != dds::ReadResult::Success) { throw std::runtime_error("Failed to load DDS texture"); } return ExtractImage(&image); } std::unique_ptr ImageLoaderDds::loadFromMemory(const std::vector& buffer) { dds::Image image; if (dds::readImage(const_cast(buffer.data()), buffer.size(), &image) != dds::ReadResult::Success) { throw std::runtime_error("Failed to load DDS texture"); } return ExtractImage(&image); } Math::Vector2i ImageLoaderDds::GetImageDimensions(const std::string& filename) { dds::Image image; if (dds::readFile(filename, &image) != dds::ReadResult::Success) { throw std::runtime_error("Failed to load DDS texture"); } Math::Vector2i result; result.x = image.width; result.y = image.height; return result; } std::unique_ptr ImageLoaderDds::ExtractImage(dds::Image* ddsImage) { auto image = std::make_unique(); image->resolution.x = ddsImage->width; image->resolution.y = ddsImage->height; image->resolution.z = 1; if (ddsImage->mipmaps.size() == 0) { throw std::runtime_error("Failed to read an image from a texture with no mipmaps"); } dds::span texture = ddsImage->mipmaps[0]; image->data = Array(texture.size_bytes()); memcpy(image->data.Data(), texture.data(), texture.size_bytes()); image->dataFormat = DataFormat::Format::UNDEFINED; switch (ddsImage->format) { case DXGI_FORMAT_R32G32B32A32_FLOAT: image->dataFormat = DataFormat::Format::R32G32B32A32_SFLOAT; break; case DXGI_FORMAT_R32G32B32A32_UINT: image->dataFormat = DataFormat::Format::R32G32B32A32_UINT; break; case DXGI_FORMAT_R32G32B32A32_SINT: image->dataFormat = DataFormat::Format::R32G32B32A32_SINT; break; case DXGI_FORMAT_R32G32B32_FLOAT: image->dataFormat = DataFormat::Format::R32G32B32_SFLOAT; break; case DXGI_FORMAT_R32G32B32_UINT: image->dataFormat = DataFormat::Format::R32G32B32_UINT; break; case DXGI_FORMAT_R32G32B32_SINT: image->dataFormat = DataFormat::Format::R32G32B32_SINT; break; case DXGI_FORMAT_R16G16B16A16_FLOAT: image->dataFormat = DataFormat::Format::R16G16B16A16_SFLOAT; break; case DXGI_FORMAT_R16G16B16A16_UNORM: image->dataFormat = DataFormat::Format::R16G16B16A16_UNORM; break; case DXGI_FORMAT_R16G16B16A16_UINT: image->dataFormat = DataFormat::Format::R16G16B16A16_UINT; break; case DXGI_FORMAT_R16G16B16A16_SNORM: image->dataFormat = DataFormat::Format::R16G16B16A16_SNORM; break; case DXGI_FORMAT_R16G16B16A16_SINT: image->dataFormat = DataFormat::Format::R16G16B16A16_SINT; break; case DXGI_FORMAT_R32G32_FLOAT: image->dataFormat = DataFormat::Format::R32G32_SFLOAT; break; case DXGI_FORMAT_R32G32_UINT: image->dataFormat = DataFormat::Format::R32G32_UINT; break; case DXGI_FORMAT_R32G32_SINT: image->dataFormat = DataFormat::Format::R32G32_SINT; break; case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: image->dataFormat = DataFormat::Format::D32_SFLOAT_S8_UINT; break; case DXGI_FORMAT_R8G8B8A8_UNORM: image->dataFormat = DataFormat::Format::R8G8B8A8_UNORM; break; case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: image->dataFormat = DataFormat::Format::R8G8B8A8_SRGB; break; case DXGI_FORMAT_R8G8B8A8_UINT: image->dataFormat = DataFormat::Format::R8G8B8A8_UINT; break; case DXGI_FORMAT_R8G8B8A8_SNORM: image->dataFormat = DataFormat::Format::R8G8B8A8_SNORM; break; case DXGI_FORMAT_R8G8B8A8_SINT: image->dataFormat = DataFormat::Format::R8G8B8A8_SINT; break; case DXGI_FORMAT_R16G16_FLOAT: image->dataFormat = DataFormat::Format::R16G16_SFLOAT; break; case DXGI_FORMAT_R16G16_UNORM: image->dataFormat = DataFormat::Format::R16G16_UNORM; break; case DXGI_FORMAT_R16G16_UINT: image->dataFormat = DataFormat::Format::R16G16_UINT; break; case DXGI_FORMAT_R16G16_SNORM: image->dataFormat = DataFormat::Format::R16G16_SNORM; break; case DXGI_FORMAT_R16G16_SINT: image->dataFormat = DataFormat::Format::R16G16_SINT; break; case DXGI_FORMAT_D32_FLOAT: image->dataFormat = DataFormat::Format::D32_SFLOAT; break; case DXGI_FORMAT_R32_FLOAT: image->dataFormat = DataFormat::Format::R32_SFLOAT; break; case DXGI_FORMAT_R32_UINT: image->dataFormat = DataFormat::Format::R32_UINT; break; case DXGI_FORMAT_R32_SINT: image->dataFormat = DataFormat::Format::R32_SINT; break; case DXGI_FORMAT_D24_UNORM_S8_UINT: image->dataFormat = DataFormat::Format::D24_UNORM_S8_UINT; break; case DXGI_FORMAT_R8G8_UNORM: image->dataFormat = DataFormat::Format::R8G8_UNORM; break; case DXGI_FORMAT_R8G8_UINT: image->dataFormat = DataFormat::Format::R8G8_UINT; break; case DXGI_FORMAT_R8G8_SNORM: image->dataFormat = DataFormat::Format::R8G8_SNORM; break; case DXGI_FORMAT_R8G8_SINT: image->dataFormat = DataFormat::Format::R8G8_SINT; break; case DXGI_FORMAT_D16_UNORM: image->dataFormat = DataFormat::Format::D16_UNORM; break; case DXGI_FORMAT_R16_FLOAT: image->dataFormat = DataFormat::Format::R16_SFLOAT; break; case DXGI_FORMAT_R16_UNORM: image->dataFormat = DataFormat::Format::R16_UNORM; break; case DXGI_FORMAT_R16_UINT: image->dataFormat = DataFormat::Format::R16_UINT; break; case DXGI_FORMAT_R16_SNORM: image->dataFormat = DataFormat::Format::R16_SNORM; break; case DXGI_FORMAT_R16_SINT: image->dataFormat = DataFormat::Format::R16_SINT; break; case DXGI_FORMAT_R8_UNORM: image->dataFormat = DataFormat::Format::R8_UNORM; break; case DXGI_FORMAT_R8_UINT: image->dataFormat = DataFormat::Format::R8_UINT; break; case DXGI_FORMAT_R8_SNORM: image->dataFormat = DataFormat::Format::R8_SNORM; break; case DXGI_FORMAT_R8_SINT: image->dataFormat = DataFormat::Format::R8_SINT; break; case DXGI_FORMAT_BC1_UNORM: image->dataFormat = DataFormat::Format::BC1_RGBA_UNORM_BLOCK; break; case DXGI_FORMAT_BC1_UNORM_SRGB: image->dataFormat = DataFormat::Format::BC1_RGBA_SRGB_BLOCK; break; case DXGI_FORMAT_BC2_UNORM: image->dataFormat = DataFormat::Format::BC2_UNORM_BLOCK; break; case DXGI_FORMAT_BC2_UNORM_SRGB: image->dataFormat = DataFormat::Format::BC2_SRGB_BLOCK; break; case DXGI_FORMAT_BC3_UNORM: image->dataFormat = DataFormat::Format::BC3_UNORM_BLOCK; break; case DXGI_FORMAT_BC3_UNORM_SRGB: image->dataFormat = DataFormat::Format::BC3_SRGB_BLOCK; break; case DXGI_FORMAT_BC4_UNORM: image->dataFormat = DataFormat::Format::BC4_UNORM_BLOCK; break; case DXGI_FORMAT_BC4_SNORM: image->dataFormat = DataFormat::Format::BC4_SNORM_BLOCK; break; case DXGI_FORMAT_BC5_UNORM: image->dataFormat = DataFormat::Format::BC5_UNORM_BLOCK; break; case DXGI_FORMAT_BC5_SNORM: image->dataFormat = DataFormat::Format::BC5_SNORM_BLOCK; break; case DXGI_FORMAT_B5G6R5_UNORM: image->dataFormat = DataFormat::Format::B5G6R5_UNORM_PACK16; break; case DXGI_FORMAT_B5G5R5A1_UNORM: image->dataFormat = DataFormat::Format::B5G5R5A1_UNORM_PACK16; break; case DXGI_FORMAT_B8G8R8A8_UNORM: image->dataFormat = DataFormat::Format::B8G8R8A8_UNORM; break; case DXGI_FORMAT_B8G8R8X8_UNORM: image->dataFormat = DataFormat::Format::B8G8R8A8_SNORM; break; case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: image->dataFormat = DataFormat::Format::B8G8R8A8_SRGB; break; case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: image->dataFormat = DataFormat::Format::B8G8R8A8_SRGB; break; case DXGI_FORMAT_BC6H_UF16: image->dataFormat = DataFormat::Format::BC6H_UFLOAT_BLOCK; break; case DXGI_FORMAT_BC6H_SF16: image->dataFormat = DataFormat::Format::BC6H_SFLOAT_BLOCK; break; case DXGI_FORMAT_BC7_UNORM: image->dataFormat = DataFormat::Format::BC7_UNORM_BLOCK; break; case DXGI_FORMAT_BC7_UNORM_SRGB: image->dataFormat = DataFormat::Format::BC7_SRGB_BLOCK; break; case DXGI_FORMAT_B4G4R4A4_UNORM: image->dataFormat = DataFormat::Format::B4G4R4A4_UNORM_PACK16; break; default: throw std::runtime_error("Unhandled DDS texture format: " + std::to_string(*reinterpret_cast(&ddsImage->format))); } return image; } }