From dbfec252d2b2c684a162da8123a1222b9dfc4878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Sat, 1 Jun 2024 07:45:45 +0200 Subject: [PATCH] created new DDS loader that's better for streaming --- Editor/ModelImporter_GLTF.cpp | 10 +- WickedEngine/Utility/dds.h | 951 ++++++++++++++ WickedEngine/Utility/dds_write.h | 399 ------ WickedEngine/Utility/tinyddsloader.h | 1161 ----------------- WickedEngine/Utility/utility_common.cpp | 3 - WickedEngine/WickedEngine_SOURCE.vcxitems | 3 +- .../WickedEngine_SOURCE.vcxitems.filters | 5 +- WickedEngine/wiHelper.cpp | 130 +- WickedEngine/wiResourceManager.cpp | 195 ++- WickedEngine/wiVersion.cpp | 2 +- third_party_software.txt | 26 - 11 files changed, 1114 insertions(+), 1771 deletions(-) create mode 100644 WickedEngine/Utility/dds.h delete mode 100644 WickedEngine/Utility/dds_write.h delete mode 100644 WickedEngine/Utility/tinyddsloader.h diff --git a/Editor/ModelImporter_GLTF.cpp b/Editor/ModelImporter_GLTF.cpp index dc75b75c8..472c6cc8c 100644 --- a/Editor/ModelImporter_GLTF.cpp +++ b/Editor/ModelImporter_GLTF.cpp @@ -4,7 +4,7 @@ #include "wiRandom.h" #include "Utility/stb_image.h" -#include "Utility/dds_write.h" +#include "Utility/dds.h" #define TINYGLTF_IMPLEMENTATION #define TINYGLTF_NO_FS @@ -1976,10 +1976,10 @@ void ImportModel_GLTF(const std::string& fileName, Scene& scene) } wi::vector dds; - dds.resize(sizeof(dds_write::Header) + wholeDataSize); - dds_write::write_header( + dds.resize(sizeof(dds::Header) + wholeDataSize); + dds::write_header( dds.data(), - dds_write::DXGI_FORMAT_R9G9B9E5_SHAREDEXP, + dds::DXGI_FORMAT_R9G9B9E5_SHAREDEXP, desc.width, desc.height, desc.mip_levels, @@ -1987,7 +1987,7 @@ void ImportModel_GLTF(const std::string& fileName, Scene& scene) true ); - size_t offset = sizeof(dds_write::Header); + size_t offset = sizeof(dds::Header); for (auto& x : hdr_datas) { std::memcpy(dds.data() + offset, x.data(), x.size() * sizeof(XMFLOAT3SE)); diff --git a/WickedEngine/Utility/dds.h b/WickedEngine/Utility/dds.h new file mode 100644 index 000000000..9d92521ee --- /dev/null +++ b/WickedEngine/Utility/dds.h @@ -0,0 +1,951 @@ +#ifndef DDS_H +#define DDS_H +// Minimal cross-platform DDS texture utility created by Turánszki János for Wicked Engine: https://github.com/turanszkij/WickedEngine +// This is not using any includes or memory allocations, and computes relative memory offsets designed for texture streaming +// Based on DDS specification: https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide#dds-file-layout +// +// How to read DDS textures: +// 1) Read the whole DDS file, or sizeof(dds::Header) bytes from the beginning of the file +// 2) Use dds::read_header() to parse the header of the DDS texture +// 3) from the dds::Header structure that was created by dds::read_header(), you can compute parameters of the texture required for loading +// 4) any function of the header returning an offset is relative to the beginning of the file, usable for texture streaming to read only the required data from files +// 5) enjoy +// +// Example: +// dds::Header header = dds::read_header(filedata, filesize); +// if(header.is_valid()) +// { +// TextureDesc desc; +// desc.width = header.width(); +// desc.mip_levels = header.mip_levels(); +// desc.array_size = header.array_size(); +// +// SubresourceData initdata; +// initdata.data_ptr = filedata + header.mip_offset(0); +// initdata.row_pitch = header.row_pitch(0); +// +// ...continue loading texture data... +// } +// +// How to write DDS textures: +// 1) Allocate memory of: sizeof(dds::Header) + your whole texture size +// 2) Use dds::write_header() to write DDS header into memory +// 3) write your texture data into memory manually after allocation + sizeof(dds::Header) +// 4) this only writes to memory, so write the result into file manually if you want to +// 5) enjoy +// +// Example: +// std::vector texturedata; // your texture data in a GPU format +// std::vector filedata; // DDS file data container +// filedata.resize(sizeof(dds::Header) + texturedata.size()); // allocate memory +// +// dds::write_header( +// filedata.data(), +// dds::DXGI_FORMAT_R8G8B8A8_UNORM, +// width, +// height, +// mip_count, // optional +// array_size, // optional +// false, // optional (is_cubemap) +// depth // optional +// ); +// std::memcpy(filedata.data() + sizeof(dds::Header), texturedata.data(), texturedata.size()); +// +// ...Or you can just freely use the structures here to write your own DDS header +// +// Note: texture data need to be in the following layout in the DDS file, tightly packed: +// - Array slice 0 / cubemap face +X +// - mipmap 0 +// - depth slice 0 +// - depth slice 1 +// - ... +// - mipmap 1 +// - depth slice 0 +// - depth slice 1 +// - ... +// - ... +// - Array slice 1 / cubemap face -X +// - mipmap 0 +// - depth slice 0 +// - depth slice 1 +// - ... +// - mipmap 1 +// - depth slice 0 +// - depth slice 1 +// - ... +// - ... +// - ... +// Note: This is similar to how you would provide the texture with DirectX 11 API's D3D11_SUBRESOURCE_DATA when creating textures +// +// Support: +// - This will only create DX10 version of DDS, doesn't support legacy +// - Tested with Texture 1D, Texture 2D, Texture 2D Array, Cubemap, Cubemap array, 3D Texture +// - Tested with uncompressed formats and block compressed +// - mipmaps: Yes +// - arrays: Yes +// +// MIT License (see the end of this file) + +namespace dds +{ + enum DDS_PIXELFORMAT_FLAGS + { + DDPF_ALPHAPIXELS = 0x1, // Texture contains alpha data; dwRGBAlphaBitMask contains valid data. + DDPF_ALPHA = 0x2, // Used in some older DDS files for alpha channel only uncompressed data (dwRGBBitCount contains the alpha channel bitcount; dwABitMask contains valid data) + DDPF_FOURCC = 0x4, // Texture contains compressed RGB data; dwFourCC contains valid data. + DDPF_RGB = 0x40, // Texture contains uncompressed RGB data; dwRGBBitCount and the RGB masks (dwRBitMask, dwGBitMask, dwBBitMask) contain valid data. + DDPF_YUV = 0x200, // Used in some older DDS files for YUV uncompressed data (dwRGBBitCount contains the YUV bit count; dwRBitMask contains the Y mask, dwGBitMask contains the U mask, dwBBitMask contains the V mask) + DDPF_LUMINANCE = 0x20000 // Used in some older DDS files for single channel color uncompressed data (dwRGBBitCount contains the luminance channel bit count; dwRBitMask contains the channel mask). Can be combined with DDPF_ALPHAPIXELS for a two channel DDS file. + }; + struct DDS_PIXELFORMAT { + unsigned dwSize; + unsigned dwFlags; + unsigned dwFourCC; + unsigned dwRGBBitCount; + unsigned dwRBitMask; + unsigned dwGBitMask; + unsigned dwBBitMask; + unsigned dwABitMask; + }; + enum DDSD_CAPS + { + DDSD_CAPS = 0x1, // Required in every .dds file. + DDSD_HEIGHT = 0x2, // Required in every .dds file. + DDSD_WIDTH = 0x4, // Required in every .dds file. + DDSD_PITCH = 0x8, // Required when pitch is provided for an uncompressed texture. + DDSD_PIXELFORMAT = 0x1000, // Required in every .dds file. + DDSD_MIPMAPCOUNT = 0x20000, // Required in a mipmapped texture. + DDSD_LINEARSIZE = 0x80000, // Required when pitch is provided for a compressed texture. + DDSD_DEPTH = 0x800000 // Required in a depth texture. + }; + enum DDSCAPS + { + DDSCAPS_COMPLEX = 0x8, // Optional; must be used on any file that contains more than one surface (a mipmap, a cubic environment map, or mipmapped volume texture). + DDSCAPS_MIPMAP = 0x400000, // Optional; should be used for a mipmap. + DDSCAPS_TEXTURE = 0x1000, // Required + }; + enum DDSCAPS2 + { + DDSCAPS2_CUBEMAP = 0x200, // Required for a cube map. + DDSCAPS2_CUBEMAP_POSITIVEX = 0x400, // Required when these surfaces are stored in a cube map. + DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800, // Required when these surfaces are stored in a cube map. + DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,// Required when these surfaces are stored in a cube map. + DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,// Required when these surfaces are stored in a cube map. + DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,// Required when these surfaces are stored in a cube map. + DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,// Required when these surfaces are stored in a cube map. + DDSCAPS2_VOLUME = 0x200000, // Required for a volume texture. + }; + typedef struct { + unsigned dwSize; + unsigned dwFlags; + unsigned dwHeight; + unsigned dwWidth; + unsigned dwPitchOrLinearSize; + unsigned dwDepth; + unsigned dwMipMapCount; + unsigned dwReserved1[11]; + DDS_PIXELFORMAT ddspf; + unsigned dwCaps; + unsigned dwCaps2; + unsigned dwCaps3; + unsigned dwCaps4; + unsigned dwReserved2; + } DDS_HEADER; + enum DXGI_FORMAT { + DXGI_FORMAT_UNKNOWN = 0, + DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, + DXGI_FORMAT_R32G32B32A32_FLOAT = 2, + DXGI_FORMAT_R32G32B32A32_UINT = 3, + DXGI_FORMAT_R32G32B32A32_SINT = 4, + DXGI_FORMAT_R32G32B32_TYPELESS = 5, + DXGI_FORMAT_R32G32B32_FLOAT = 6, + DXGI_FORMAT_R32G32B32_UINT = 7, + DXGI_FORMAT_R32G32B32_SINT = 8, + DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, + DXGI_FORMAT_R16G16B16A16_FLOAT = 10, + DXGI_FORMAT_R16G16B16A16_UNORM = 11, + DXGI_FORMAT_R16G16B16A16_UINT = 12, + DXGI_FORMAT_R16G16B16A16_SNORM = 13, + DXGI_FORMAT_R16G16B16A16_SINT = 14, + DXGI_FORMAT_R32G32_TYPELESS = 15, + DXGI_FORMAT_R32G32_FLOAT = 16, + DXGI_FORMAT_R32G32_UINT = 17, + DXGI_FORMAT_R32G32_SINT = 18, + DXGI_FORMAT_R32G8X24_TYPELESS = 19, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, + DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, + DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, + DXGI_FORMAT_R10G10B10A2_UNORM = 24, + DXGI_FORMAT_R10G10B10A2_UINT = 25, + DXGI_FORMAT_R11G11B10_FLOAT = 26, + DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, + DXGI_FORMAT_R8G8B8A8_UNORM = 28, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, + DXGI_FORMAT_R8G8B8A8_UINT = 30, + DXGI_FORMAT_R8G8B8A8_SNORM = 31, + DXGI_FORMAT_R8G8B8A8_SINT = 32, + DXGI_FORMAT_R16G16_TYPELESS = 33, + DXGI_FORMAT_R16G16_FLOAT = 34, + DXGI_FORMAT_R16G16_UNORM = 35, + DXGI_FORMAT_R16G16_UINT = 36, + DXGI_FORMAT_R16G16_SNORM = 37, + DXGI_FORMAT_R16G16_SINT = 38, + DXGI_FORMAT_R32_TYPELESS = 39, + DXGI_FORMAT_D32_FLOAT = 40, + DXGI_FORMAT_R32_FLOAT = 41, + DXGI_FORMAT_R32_UINT = 42, + DXGI_FORMAT_R32_SINT = 43, + DXGI_FORMAT_R24G8_TYPELESS = 44, + DXGI_FORMAT_D24_UNORM_S8_UINT = 45, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, + DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, + DXGI_FORMAT_R8G8_TYPELESS = 48, + DXGI_FORMAT_R8G8_UNORM = 49, + DXGI_FORMAT_R8G8_UINT = 50, + DXGI_FORMAT_R8G8_SNORM = 51, + DXGI_FORMAT_R8G8_SINT = 52, + DXGI_FORMAT_R16_TYPELESS = 53, + DXGI_FORMAT_R16_FLOAT = 54, + DXGI_FORMAT_D16_UNORM = 55, + DXGI_FORMAT_R16_UNORM = 56, + DXGI_FORMAT_R16_UINT = 57, + DXGI_FORMAT_R16_SNORM = 58, + DXGI_FORMAT_R16_SINT = 59, + DXGI_FORMAT_R8_TYPELESS = 60, + DXGI_FORMAT_R8_UNORM = 61, + DXGI_FORMAT_R8_UINT = 62, + DXGI_FORMAT_R8_SNORM = 63, + DXGI_FORMAT_R8_SINT = 64, + DXGI_FORMAT_A8_UNORM = 65, + DXGI_FORMAT_R1_UNORM = 66, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, + DXGI_FORMAT_R8G8_B8G8_UNORM = 68, + DXGI_FORMAT_G8R8_G8B8_UNORM = 69, + DXGI_FORMAT_BC1_TYPELESS = 70, + DXGI_FORMAT_BC1_UNORM = 71, + DXGI_FORMAT_BC1_UNORM_SRGB = 72, + DXGI_FORMAT_BC2_TYPELESS = 73, + DXGI_FORMAT_BC2_UNORM = 74, + DXGI_FORMAT_BC2_UNORM_SRGB = 75, + DXGI_FORMAT_BC3_TYPELESS = 76, + DXGI_FORMAT_BC3_UNORM = 77, + DXGI_FORMAT_BC3_UNORM_SRGB = 78, + DXGI_FORMAT_BC4_TYPELESS = 79, + DXGI_FORMAT_BC4_UNORM = 80, + DXGI_FORMAT_BC4_SNORM = 81, + DXGI_FORMAT_BC5_TYPELESS = 82, + DXGI_FORMAT_BC5_UNORM = 83, + DXGI_FORMAT_BC5_SNORM = 84, + DXGI_FORMAT_B5G6R5_UNORM = 85, + DXGI_FORMAT_B5G5R5A1_UNORM = 86, + DXGI_FORMAT_B8G8R8A8_UNORM = 87, + DXGI_FORMAT_B8G8R8X8_UNORM = 88, + DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, + DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, + DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, + DXGI_FORMAT_BC6H_TYPELESS = 94, + DXGI_FORMAT_BC6H_UF16 = 95, + DXGI_FORMAT_BC6H_SF16 = 96, + DXGI_FORMAT_BC7_TYPELESS = 97, + DXGI_FORMAT_BC7_UNORM = 98, + DXGI_FORMAT_BC7_UNORM_SRGB = 99, + DXGI_FORMAT_AYUV = 100, + DXGI_FORMAT_Y410 = 101, + DXGI_FORMAT_Y416 = 102, + DXGI_FORMAT_NV12 = 103, + DXGI_FORMAT_P010 = 104, + DXGI_FORMAT_P016 = 105, + DXGI_FORMAT_420_OPAQUE = 106, + DXGI_FORMAT_YUY2 = 107, + DXGI_FORMAT_Y210 = 108, + DXGI_FORMAT_Y216 = 109, + DXGI_FORMAT_NV11 = 110, + DXGI_FORMAT_AI44 = 111, + DXGI_FORMAT_IA44 = 112, + DXGI_FORMAT_P8 = 113, + DXGI_FORMAT_A8P8 = 114, + DXGI_FORMAT_B4G4R4A4_UNORM = 115, + DXGI_FORMAT_P208 = 130, + DXGI_FORMAT_V208 = 131, + DXGI_FORMAT_V408 = 132, + DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE, + DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE, + DXGI_FORMAT_FORCE_DWORD = 0xffffffff + }; + enum D3D10_RESOURCE_DIMENSION { + D3D10_RESOURCE_DIMENSION_UNKNOWN = 0, + D3D10_RESOURCE_DIMENSION_BUFFER = 1, + D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2, + D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3, + D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4 + }; + enum DDS_RESOURCE_MISC_TEXTURECUBE + { + DDS_RESOURCE_MISC_TEXTURECUBE = 0x4, // Indicates a 2D texture is a cube-map texture. + }; + enum DDS_ALPHA_MODE + { + DDS_ALPHA_MODE_UNKNOWN = 0x0, // Alpha channel content is unknown. This is the value for legacy files, which typically is assumed to be 'straight' alpha. + DDS_ALPHA_MODE_STRAIGHT = 0x1, // Any alpha channel content is presumed to use straight alpha. + DDS_ALPHA_MODE_PREMULTIPLIED = 0x2, // Any alpha channel content is using premultiplied alpha. The only legacy file formats that indicate this information are 'DX2' and 'DX4'. + DDS_ALPHA_MODE_OPAQUE = 0x3, // Any alpha channel content is all set to fully opaque. + DDS_ALPHA_MODE_CUSTOM = 0x4, // Any alpha channel content is being used as a 4th channel and is not intended to represent transparency (straight or premultiplied). + }; + typedef struct { + DXGI_FORMAT dxgiFormat; + D3D10_RESOURCE_DIMENSION resourceDimension; + unsigned miscFlag; + unsigned arraySize; + unsigned miscFlags2; + } DDS_HEADER_DXT10; + + static constexpr unsigned fourcc(char a, char b, char c, char d) + { + return (((unsigned)(d) << 24) | ((unsigned)(c) << 16) | ((unsigned)(b) << 8) | (unsigned)(a)); + } + + struct Header + { + unsigned magic; + DDS_HEADER header; + DDS_HEADER_DXT10 header10; + + // Returns true if this structure can be used, false otherwise + constexpr bool is_valid() const + { + return + magic == fourcc('D', 'D', 'S', ' ') && + header.ddspf.dwSize == sizeof(DDS_PIXELFORMAT); + } + // Returns true if the header10 member is valid + constexpr bool is_dx10() const + { + return + (header.ddspf.dwFlags & DDPF_FOURCC) && + header.ddspf.dwFourCC == fourcc('D', 'X', '1', '0'); + } + // returns the width of the texture in pixels + constexpr unsigned width() const + { + if(header.dwFlags & DDSD_WIDTH) + return header.dwWidth; + return 1; + } + // returns the height of the texture in pixels + constexpr unsigned height() const + { + if (header.dwFlags & DDSD_HEIGHT) + return header.dwHeight; + return 1; + } + // returns the depth of the texture in pixels + constexpr unsigned depth() const + { + return header.dwDepth < 1 ? 1 : header.dwDepth; + } + // returns the mipmap levels in the texture per slice + constexpr unsigned mip_levels() const + { + if ((header.dwFlags & DDSD_MIPMAPCOUNT) && (header.dwCaps & DDSCAPS_COMPLEX)) + return header.dwMipMapCount > 0 ? header.dwMipMapCount : 1; + return 1; + } + // returns the number of slices in the texture + constexpr unsigned array_size() const + { + if (!is_dx10()) + return 1; + unsigned count = 0; + if (is_cubemap()) + count = header10.arraySize * 6; + else + count = header10.arraySize; + count = count < 1 ? 1 : count; + return count; + } + // returns the format of the texture in the DXGI_FORMAT that is complatible with DX10, even when the texture is using legacy format + constexpr DXGI_FORMAT format() const + { + if (!is_dx10()) + { + if (header.ddspf.dwFlags & DDPF_RGB) + { + switch (header.ddspf.dwRGBBitCount) + { + case 32: + if (header.ddspf.dwRBitMask == 0x000000ff && + header.ddspf.dwGBitMask == 0x0000ff00 && + header.ddspf.dwBBitMask == 0x00ff0000 && + header.ddspf.dwABitMask == 0xff000000) { + return DXGI_FORMAT_R8G8B8A8_UNORM; + } + if (header.ddspf.dwRBitMask == 0x00ff0000 && + header.ddspf.dwGBitMask == 0x0000ff00 && + header.ddspf.dwBBitMask == 0x000000ff && + header.ddspf.dwABitMask == 0xff000000) { + return DXGI_FORMAT_B8G8R8A8_UNORM; + } + if (header.ddspf.dwRBitMask == 0x00ff0000 && + header.ddspf.dwGBitMask == 0x0000ff00 && + header.ddspf.dwBBitMask == 0x000000ff && + header.ddspf.dwABitMask == 0x00000000) { + return DXGI_FORMAT_B8G8R8X8_UNORM; + } + + if (header.ddspf.dwRBitMask == 0x0000ffff && + header.ddspf.dwGBitMask == 0xffff0000 && + header.ddspf.dwBBitMask == 0x00000000 && + header.ddspf.dwABitMask == 0x00000000) { + return DXGI_FORMAT_R16G16_UNORM; + } + + if (header.ddspf.dwRBitMask == 0xffffffff && + header.ddspf.dwGBitMask == 0x00000000 && + header.ddspf.dwBBitMask == 0x00000000 && + header.ddspf.dwABitMask == 0x00000000) { + return DXGI_FORMAT_R32_FLOAT; + } + break; + case 24: + break; + case 16: + if (header.ddspf.dwRBitMask == 0x7c00 && header.ddspf.dwGBitMask == 0x03e0 && + header.ddspf.dwBBitMask == 0x001f && header.ddspf.dwABitMask == 0x8000) { + return DXGI_FORMAT_B5G5R5A1_UNORM; + } + if (header.ddspf.dwRBitMask == 0xf800 && header.ddspf.dwGBitMask == 0x07e0 && + header.ddspf.dwBBitMask == 0x001f && header.ddspf.dwABitMask == 0x0000) { + return DXGI_FORMAT_B5G6R5_UNORM; + } + + if (header.ddspf.dwRBitMask == 0x0f00 && header.ddspf.dwGBitMask == 0x00f0 && + header.ddspf.dwBBitMask == 0x000f && header.ddspf.dwABitMask == 0xf000) { + return DXGI_FORMAT_B4G4R4A4_UNORM; + } + break; + default: + break; + } + } + else if (header.ddspf.dwFlags & DDPF_LUMINANCE) { + if (8 == header.ddspf.dwRGBBitCount) { + if (header.ddspf.dwRBitMask == 0x000000ff && header.ddspf.dwGBitMask == 0x00000000 && + header.ddspf.dwBBitMask == 0x00000000 && header.ddspf.dwABitMask == 0x00000000) { + return DXGI_FORMAT_R8_UNORM; + } + if (header.ddspf.dwRBitMask == 0x000000ff && header.ddspf.dwGBitMask == 0x0000ff00 && + header.ddspf.dwBBitMask == 0x00000000 && header.ddspf.dwABitMask == 0x00000000) { + return DXGI_FORMAT_R8G8_UNORM; + } + } + if (16 == header.ddspf.dwRGBBitCount) { + if (header.ddspf.dwRBitMask == 0x0000ffff && header.ddspf.dwGBitMask == 0x00000000 && + header.ddspf.dwBBitMask == 0x00000000 && header.ddspf.dwABitMask == 0x00000000) { + return DXGI_FORMAT_R16_UNORM; + } + if (header.ddspf.dwRBitMask == 0x000000ff && header.ddspf.dwGBitMask == 0x0000ff00 && + header.ddspf.dwBBitMask == 0x00000000 && header.ddspf.dwABitMask == 0x00000000) { + return DXGI_FORMAT_R8G8_UNORM; + } + } + } + else if (header.ddspf.dwFlags & DDPF_ALPHA) { + if (8 == header.ddspf.dwRGBBitCount) { + return DXGI_FORMAT_A8_UNORM; + } + } + else if (header.ddspf.dwFlags & DDPF_FOURCC) { + if (fourcc('D', 'X', 'T', '1') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_BC1_UNORM; + } + if (fourcc('D', 'X', 'T', '3') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_BC2_UNORM; + } + if (fourcc('D', 'X', 'T', '5') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_BC3_UNORM; + } + + if (fourcc('D', 'X', 'T', '4') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_BC2_UNORM; + } + if (fourcc('D', 'X', 'T', '5') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_BC3_UNORM; + } + + if (fourcc('A', 'T', 'I', '1') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_BC4_UNORM; + } + if (fourcc('B', 'C', '4', 'U') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_BC4_UNORM; + } + if (fourcc('B', 'C', '4', 'S') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_BC4_SNORM; + } + + if (fourcc('A', 'T', 'I', '2') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_BC5_UNORM; + } + if (fourcc('B', 'C', '5', 'U') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_BC5_UNORM; + } + if (fourcc('B', 'C', '5', 'S') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_BC5_SNORM; + } + + if (fourcc('R', 'G', 'B', 'G') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_R8G8_B8G8_UNORM; + } + if (fourcc('G', 'R', 'G', 'B') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_G8R8_G8B8_UNORM; + } + + if (fourcc('Y', 'U', 'Y', '2') == header.ddspf.dwFourCC) { + return DXGI_FORMAT_YUY2; + } + + switch (header.ddspf.dwFourCC) { + case 36: + return DXGI_FORMAT_R16G16B16A16_UNORM; + case 110: + return DXGI_FORMAT_R16G16B16A16_SNORM; + case 111: + return DXGI_FORMAT_R16_FLOAT; + case 112: + return DXGI_FORMAT_R16G16_FLOAT; + case 113: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + case 114: + return DXGI_FORMAT_R32_FLOAT; + case 115: + return DXGI_FORMAT_R32G32_FLOAT; + case 116: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + } + } + return DXGI_FORMAT_UNKNOWN; + } + return header10.dxgiFormat; + } + // returns tru if the texture is a cubemap, false otherwise + constexpr bool is_cubemap() const + { + if (!is_dx10()) + return false; + return + (header.dwCaps & DDSCAPS_COMPLEX) && + (header.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEX) && + (header.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) && + (header.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEY) && + (header.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) && + (header.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) && + (header.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) && + (header10.miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE) + ; + } + // returns true if the texture is one dimensional, false otherwise + constexpr bool is_1d() const + { + if (!is_dx10()) + return false; + return header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D; + } + // returns true if the texture is three dimensional, false otherwise + constexpr bool is_3d() const + { + if (!is_dx10()) + return false; + return + (header.dwCaps2 & DDSCAPS2_VOLUME) && + header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D + ; + } + // returns the number of bits per element. Element refers to a block of pixels if the texture is block compressed, or a single pixel otherwise + constexpr unsigned bits_per_element() const + { + switch (format()) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return 128; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 96; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT_Y416: + case DXGI_FORMAT_Y210: + case DXGI_FORMAT_Y216: + return 64; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_Y410: + case DXGI_FORMAT_YUY2: + return 32; + + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + return 24; + + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_A8P8: + case DXGI_FORMAT_B4G4R4A4_UNORM: + return 16; + + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_NV11: + return 12; + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + return 8; + + case DXGI_FORMAT_R1_UNORM: + return 1; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return 64; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 128; + default: + return 0; + } + } + // returns 1 for non-block compressed formats, or the block size if it's compressed + constexpr unsigned block_size() const + { + switch (format()) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return 4; + default: + return 1; + } + } + // returns the size of a specific mipmap in bytes + constexpr unsigned long long mip_size(unsigned mip) const + { + const unsigned bpe = bits_per_element(); + const unsigned blocksize = block_size(); + unsigned num_blocks_x = (width() + blocksize - 1) / blocksize; + unsigned num_blocks_y = (height() + blocksize - 1) / blocksize; + unsigned num_elements_z = depth(); + num_blocks_x >>= mip; + num_blocks_y >>= mip; + num_elements_z >>= mip; + num_blocks_x = num_blocks_x < 1 ? 1 : num_blocks_x; + num_blocks_y = num_blocks_y < 1 ? 1 : num_blocks_y; + num_elements_z = num_elements_z < 1 ? 1 : num_elements_z; + return num_blocks_x * num_blocks_y * num_elements_z * bpe / 8ull; + } + // returns the size of one slice in bytes + constexpr unsigned long long slice_size() const + { + const unsigned mips = mip_levels(); + unsigned long long size = 0; + for (unsigned mip = 0; mip < mips; ++mip) + { + size += mip_size(mip); + } + return size; + } + // returns the size of the whole pixel data in bytes, including all slices and mipmaps + constexpr unsigned long long data_size() const + { + return array_size() * slice_size(); + } + // returns the offset of the pixel data relative to the beginning of the file, in bytes + constexpr unsigned long long data_offset() const + { + unsigned long long offset = sizeof(Header); + if (!is_dx10()) + offset -= sizeof(Header::header10); + return offset; + } + // returns the offset of a specific slice relative to the beginning of the file, in bytes + constexpr unsigned long long slice_offset(unsigned slice) const + { + return data_offset() + slice_size() * slice; + } + // returns the offset of a specific mipmap of a specific slice relative to the beginning of the file, in bytes + constexpr unsigned long long mip_offset(unsigned mip, unsigned slice = 0) const + { + unsigned long long offset = slice_offset(slice); + const unsigned mips = mip_levels(); + for (unsigned i = 0; i < mip; ++i) + { + offset += mip_size(i); + } + return offset; + } + // returns the size of one row in a specific mip level in bytes + constexpr unsigned row_pitch(unsigned mip) const + { + const unsigned bpe = bits_per_element(); + const unsigned blocksize = block_size(); + unsigned num_blocks_x = (width() + blocksize - 1) / blocksize; + num_blocks_x >>= mip; + num_blocks_x = num_blocks_x < 1 ? 1 : num_blocks_x; + return num_blocks_x * bpe / 8; + } + // returns the size of a specific slice at a specific mip level in bytes + constexpr unsigned slice_pitch(unsigned mip) const + { + const unsigned blocksize = block_size(); + unsigned num_blocks_y = (width() + blocksize - 1) / blocksize; + unsigned num_elements_z = depth(); + num_blocks_y >>= mip; + num_elements_z >>= mip; + num_blocks_y = num_blocks_y < 1 ? 1 : num_blocks_y; + num_elements_z = num_elements_z < 1 ? 1 : num_elements_z; + return row_pitch(mip) * num_blocks_y * num_elements_z; + } + }; + + // Read DDS header from memory + // data: pointer to memory, this should be the very start of the DDS file (fourcc bytes included) + // size: size of memory that data points to. It should be sizeof(dds::Header) or larger + // + // returns dds::Header, which you can use to determine relative memory offsets and sizes required to reference certain parts of the texture + inline Header read_header( + const void* data, + unsigned long long size + ) + { + Header h = {}; + if (data == nullptr) + return h; // invalid pointer + if (size < sizeof(Header::magic) + sizeof(Header::header)) + return h; // magic and header is a must have + h.magic = *(const unsigned*)data; + if (h.magic != fourcc('D', 'D', 'S', ' ')) + return h; // fourcc is invalid + + h.header = *(const DDS_HEADER*)((const char*)data + sizeof(h.magic)); + if (size >= sizeof(Header) && h.is_dx10()) + { + h.header10 = (*(const Header*)data).header10; + } + + return h; + } + + // Write the DDS header into memory. + // dst: destination file in memory, must be at least of sizeof(dds::Header) + // format: data format of texture data that will be placed after header + // width: width of top mip level + // height: height of top mip level (you can set this to 0 to indicate 1D texture) + // mip_levels: number of mip levels in the file + // array_size: number of slices in the file. For cubemaps, there is one slice for every face. For 3D texture, there is always only 1 slice. + // is_cubemap: whether the texture is a cubemap. If it is a cubemap, it must have at least array_size = 6 + // depth: depth of 3D texture (you can set this to 0 to indicate that the texture is not 3D) + inline void write_header( + void* dst, + DXGI_FORMAT format, + unsigned int width, + unsigned int height, + unsigned int mip_levels = 1, + unsigned int array_size = 1, + bool is_cubemap = false, + unsigned int depth = 0 + ) + { + Header h = {}; + h.magic = fourcc('D', 'D', 'S', ' '); + h.header.dwSize = sizeof(DDS_HEADER); + h.header.dwFlags = + DDSD_CAPS | + DDSD_WIDTH | + DDSD_HEIGHT | + DDSD_PIXELFORMAT | + DDSD_MIPMAPCOUNT + ; + h.header.dwWidth = width; + h.header.dwHeight = height; + h.header.dwDepth = depth; + h.header.dwMipMapCount = mip_levels; + h.header.ddspf.dwSize = sizeof(DDS_PIXELFORMAT); + h.header.ddspf.dwFlags = DDPF_FOURCC; + h.header.ddspf.dwFourCC = fourcc('D', 'X', '1', '0'); + h.header.dwCaps = DDSCAPS_TEXTURE; + + h.header10.dxgiFormat = format; + h.header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; + h.header10.miscFlags2 = DDS_ALPHA_MODE_UNKNOWN; + + if (is_cubemap) + { + h.header10.arraySize = array_size / 6; + h.header.dwCaps |= DDSCAPS_COMPLEX; + h.header.dwCaps2 = + DDSCAPS2_CUBEMAP | + DDSCAPS2_CUBEMAP_POSITIVEX | + DDSCAPS2_CUBEMAP_NEGATIVEX | + DDSCAPS2_CUBEMAP_POSITIVEY | + DDSCAPS2_CUBEMAP_NEGATIVEY | + DDSCAPS2_CUBEMAP_POSITIVEZ | + DDSCAPS2_CUBEMAP_NEGATIVEZ + ; + h.header10.miscFlag = DDS_RESOURCE_MISC_TEXTURECUBE; + } + else if (depth > 0) + { + h.header10.arraySize = 1; + h.header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D; + h.header.dwCaps2 = DDSCAPS2_VOLUME; + } + else + { + h.header10.arraySize = array_size; + } + + if (height == 0) + { + h.header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE1D; + h.header.dwHeight = 1; + } + if (mip_levels > 1) + { + h.header.dwCaps |= DDSCAPS_COMPLEX; + } + + *(Header*)dst = h; + } +} + +#endif // DDS_H + +//Copyright(c) 2024 Turánszki János +// +//Permission is hereby granted, free of charge, to any person obtaining a copy +//of this software and associated documentation files(the "Software"), to deal +//in the Software without restriction, including without limitation the rights +//to use, copy, modify, merge, publish, distribute, sublicense, and /or sell +//copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions : +// +//The above copyright notice and this permission notice shall be included in +//all copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +//THE SOFTWARE. diff --git a/WickedEngine/Utility/dds_write.h b/WickedEngine/Utility/dds_write.h deleted file mode 100644 index b85dc744b..000000000 --- a/WickedEngine/Utility/dds_write.h +++ /dev/null @@ -1,399 +0,0 @@ -#ifndef DDS_WRITE_H -#define DDS_WRITE_H -// Minimal DDS file writer utility created by Turánszki János for Wicked Engine: https://github.com/turanszkij/WickedEngine -// Based on DDS specification: https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide#dds-file-layout -// -// Usage: -// 1) Allocate memory of: sizeof(dds_write::Header) + your whole texture size -// 2) Use dds_write::write_header() to write DDS header into memory -// 3) write your texture data into memory manually after allocation + sizeof(dds_write::Header) -// 4) this only writes to memory, so write the result into file manually if you want to -// 5) enjoy -// -// Example: -// std::vector texturedata; // your texture data in a GPU format -// std::vector filedata; // DDS file data container -// filedata.resize(sizeof(dds_write::Header) + texturedata.size()); // allocate memory -// -// dds_write::write_header( -// filedata.data(), -// dds_write::DXGI_FORMAT_R8G8B8A8_UNORM, -// width, -// height, -// mip_count, // optional -// array_size, // optional -// false, // optional (is_cubemap) -// depth // optional -// ); -// std::memcpy(filedata.data() + sizeof(dds_write::Header), texturedata.data(), texturedata.size()); -// -// ...Or you can just freely use the structures here to write your own DDS header -// -// Note: texture data need to be in the following layout in the DDS file, tightly packed: -// - Array slice 0 / cubemap face +X -// - mipmap 0 -// - depth slice 0 -// - depth slice 1 -// - ... -// - mipmap 1 -// - depth slice 0 -// - depth slice 1 -// - ... -// - ... -// - Array slice 1 / cubemap face -X -// - mipmap 0 -// - depth slice 0 -// - depth slice 1 -// - ... -// - mipmap 1 -// - depth slice 0 -// - depth slice 1 -// - ... -// - ... -// - ... -// Note: This is similar to how you would provide the texture with DirectX 11 API's D3D11_SUBRESOURCE_DATA when creating textures -// -// Support: -// - This will only create DX10 version of DDS, doesn't support legacy -// - Tested with Texture 1D, Texture 2D, Texture 2D Array, Cubemap, Cubemap array, 3D Texture -// - Tested with uncompressed formats and block compressed -// - mipmaps: Yes -// - arrays: Yes -// -// MIT License (see the end of this file) - -namespace dds_write -{ - using DWORD = unsigned; - using UINT = unsigned; - - enum DDS_PIXELFORMAT_FLAGS - { - DDPF_ALPHAPIXELS = 0x1, // Texture contains alpha data; dwRGBAlphaBitMask contains valid data. - DDPF_ALPHA = 0x2, // Used in some older DDS files for alpha channel only uncompressed data (dwRGBBitCount contains the alpha channel bitcount; dwABitMask contains valid data) - DDPF_FOURCC = 0x4, // Texture contains compressed RGB data; dwFourCC contains valid data. - DDPF_RGB = 0x40, // Texture contains uncompressed RGB data; dwRGBBitCount and the RGB masks (dwRBitMask, dwGBitMask, dwBBitMask) contain valid data. - DDPF_YUV = 0x200, // Used in some older DDS files for YUV uncompressed data (dwRGBBitCount contains the YUV bit count; dwRBitMask contains the Y mask, dwGBitMask contains the U mask, dwBBitMask contains the V mask) - DDPF_LUMINANCE = 0x20000 // Used in some older DDS files for single channel color uncompressed data (dwRGBBitCount contains the luminance channel bit count; dwRBitMask contains the channel mask). Can be combined with DDPF_ALPHAPIXELS for a two channel DDS file. - }; - struct DDS_PIXELFORMAT { - DWORD dwSize; - DWORD dwFlags; - DWORD dwFourCC; - DWORD dwRGBBitCount; - DWORD dwRBitMask; - DWORD dwGBitMask; - DWORD dwBBitMask; - DWORD dwABitMask; - }; - enum DDSD_CAPS - { - DDSD_CAPS = 0x1, // Required in every .dds file. - DDSD_HEIGHT = 0x2, // Required in every .dds file. - DDSD_WIDTH = 0x4, // Required in every .dds file. - DDSD_PITCH = 0x8, // Required when pitch is provided for an uncompressed texture. - DDSD_PIXELFORMAT = 0x1000, // Required in every .dds file. - DDSD_MIPMAPCOUNT = 0x20000, // Required in a mipmapped texture. - DDSD_LINEARSIZE = 0x80000, // Required when pitch is provided for a compressed texture. - DDSD_DEPTH = 0x800000 // Required in a depth texture. - }; - enum DDSCAPS - { - DDSCAPS_COMPLEX = 0x8, // Optional; must be used on any file that contains more than one surface (a mipmap, a cubic environment map, or mipmapped volume texture). - DDSCAPS_MIPMAP = 0x400000, // Optional; should be used for a mipmap. - DDSCAPS_TEXTURE = 0x1000, // Required - }; - enum DDSCAPS2 - { - DDSCAPS2_CUBEMAP = 0x200, // Required for a cube map. - DDSCAPS2_CUBEMAP_POSITIVEX = 0x400, // Required when these surfaces are stored in a cube map. - DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800, // Required when these surfaces are stored in a cube map. - DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,// Required when these surfaces are stored in a cube map. - DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,// Required when these surfaces are stored in a cube map. - DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,// Required when these surfaces are stored in a cube map. - DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,// Required when these surfaces are stored in a cube map. - DDSCAPS2_VOLUME = 0x200000, // Required for a volume texture. - }; - typedef struct { - DWORD dwSize; - DWORD dwFlags; - DWORD dwHeight; - DWORD dwWidth; - DWORD dwPitchOrLinearSize; - DWORD dwDepth; - DWORD dwMipMapCount; - DWORD dwReserved1[11]; - DDS_PIXELFORMAT ddspf; - DWORD dwCaps; - DWORD dwCaps2; - DWORD dwCaps3; - DWORD dwCaps4; - DWORD dwReserved2; - } DDS_HEADER; - enum DXGI_FORMAT { - DXGI_FORMAT_UNKNOWN = 0, - DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, - DXGI_FORMAT_R32G32B32A32_FLOAT = 2, - DXGI_FORMAT_R32G32B32A32_UINT = 3, - DXGI_FORMAT_R32G32B32A32_SINT = 4, - DXGI_FORMAT_R32G32B32_TYPELESS = 5, - DXGI_FORMAT_R32G32B32_FLOAT = 6, - DXGI_FORMAT_R32G32B32_UINT = 7, - DXGI_FORMAT_R32G32B32_SINT = 8, - DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, - DXGI_FORMAT_R16G16B16A16_FLOAT = 10, - DXGI_FORMAT_R16G16B16A16_UNORM = 11, - DXGI_FORMAT_R16G16B16A16_UINT = 12, - DXGI_FORMAT_R16G16B16A16_SNORM = 13, - DXGI_FORMAT_R16G16B16A16_SINT = 14, - DXGI_FORMAT_R32G32_TYPELESS = 15, - DXGI_FORMAT_R32G32_FLOAT = 16, - DXGI_FORMAT_R32G32_UINT = 17, - DXGI_FORMAT_R32G32_SINT = 18, - DXGI_FORMAT_R32G8X24_TYPELESS = 19, - DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, - DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, - DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, - DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, - DXGI_FORMAT_R10G10B10A2_UNORM = 24, - DXGI_FORMAT_R10G10B10A2_UINT = 25, - DXGI_FORMAT_R11G11B10_FLOAT = 26, - DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, - DXGI_FORMAT_R8G8B8A8_UNORM = 28, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, - DXGI_FORMAT_R8G8B8A8_UINT = 30, - DXGI_FORMAT_R8G8B8A8_SNORM = 31, - DXGI_FORMAT_R8G8B8A8_SINT = 32, - DXGI_FORMAT_R16G16_TYPELESS = 33, - DXGI_FORMAT_R16G16_FLOAT = 34, - DXGI_FORMAT_R16G16_UNORM = 35, - DXGI_FORMAT_R16G16_UINT = 36, - DXGI_FORMAT_R16G16_SNORM = 37, - DXGI_FORMAT_R16G16_SINT = 38, - DXGI_FORMAT_R32_TYPELESS = 39, - DXGI_FORMAT_D32_FLOAT = 40, - DXGI_FORMAT_R32_FLOAT = 41, - DXGI_FORMAT_R32_UINT = 42, - DXGI_FORMAT_R32_SINT = 43, - DXGI_FORMAT_R24G8_TYPELESS = 44, - DXGI_FORMAT_D24_UNORM_S8_UINT = 45, - DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, - DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, - DXGI_FORMAT_R8G8_TYPELESS = 48, - DXGI_FORMAT_R8G8_UNORM = 49, - DXGI_FORMAT_R8G8_UINT = 50, - DXGI_FORMAT_R8G8_SNORM = 51, - DXGI_FORMAT_R8G8_SINT = 52, - DXGI_FORMAT_R16_TYPELESS = 53, - DXGI_FORMAT_R16_FLOAT = 54, - DXGI_FORMAT_D16_UNORM = 55, - DXGI_FORMAT_R16_UNORM = 56, - DXGI_FORMAT_R16_UINT = 57, - DXGI_FORMAT_R16_SNORM = 58, - DXGI_FORMAT_R16_SINT = 59, - DXGI_FORMAT_R8_TYPELESS = 60, - DXGI_FORMAT_R8_UNORM = 61, - DXGI_FORMAT_R8_UINT = 62, - DXGI_FORMAT_R8_SNORM = 63, - DXGI_FORMAT_R8_SINT = 64, - DXGI_FORMAT_A8_UNORM = 65, - DXGI_FORMAT_R1_UNORM = 66, - DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, - DXGI_FORMAT_R8G8_B8G8_UNORM = 68, - DXGI_FORMAT_G8R8_G8B8_UNORM = 69, - DXGI_FORMAT_BC1_TYPELESS = 70, - DXGI_FORMAT_BC1_UNORM = 71, - DXGI_FORMAT_BC1_UNORM_SRGB = 72, - DXGI_FORMAT_BC2_TYPELESS = 73, - DXGI_FORMAT_BC2_UNORM = 74, - DXGI_FORMAT_BC2_UNORM_SRGB = 75, - DXGI_FORMAT_BC3_TYPELESS = 76, - DXGI_FORMAT_BC3_UNORM = 77, - DXGI_FORMAT_BC3_UNORM_SRGB = 78, - DXGI_FORMAT_BC4_TYPELESS = 79, - DXGI_FORMAT_BC4_UNORM = 80, - DXGI_FORMAT_BC4_SNORM = 81, - DXGI_FORMAT_BC5_TYPELESS = 82, - DXGI_FORMAT_BC5_UNORM = 83, - DXGI_FORMAT_BC5_SNORM = 84, - DXGI_FORMAT_B5G6R5_UNORM = 85, - DXGI_FORMAT_B5G5R5A1_UNORM = 86, - DXGI_FORMAT_B8G8R8A8_UNORM = 87, - DXGI_FORMAT_B8G8R8X8_UNORM = 88, - DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, - DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, - DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, - DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, - DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, - DXGI_FORMAT_BC6H_TYPELESS = 94, - DXGI_FORMAT_BC6H_UF16 = 95, - DXGI_FORMAT_BC6H_SF16 = 96, - DXGI_FORMAT_BC7_TYPELESS = 97, - DXGI_FORMAT_BC7_UNORM = 98, - DXGI_FORMAT_BC7_UNORM_SRGB = 99, - DXGI_FORMAT_AYUV = 100, - DXGI_FORMAT_Y410 = 101, - DXGI_FORMAT_Y416 = 102, - DXGI_FORMAT_NV12 = 103, - DXGI_FORMAT_P010 = 104, - DXGI_FORMAT_P016 = 105, - DXGI_FORMAT_420_OPAQUE = 106, - DXGI_FORMAT_YUY2 = 107, - DXGI_FORMAT_Y210 = 108, - DXGI_FORMAT_Y216 = 109, - DXGI_FORMAT_NV11 = 110, - DXGI_FORMAT_AI44 = 111, - DXGI_FORMAT_IA44 = 112, - DXGI_FORMAT_P8 = 113, - DXGI_FORMAT_A8P8 = 114, - DXGI_FORMAT_B4G4R4A4_UNORM = 115, - DXGI_FORMAT_P208 = 130, - DXGI_FORMAT_V208 = 131, - DXGI_FORMAT_V408 = 132, - DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE, - DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE, - DXGI_FORMAT_FORCE_UINT = 0xffffffff - }; - enum D3D10_RESOURCE_DIMENSION { - D3D10_RESOURCE_DIMENSION_UNKNOWN = 0, - D3D10_RESOURCE_DIMENSION_BUFFER = 1, - D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2, - D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3, - D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4 - }; - enum DDS_RESOURCE_MISC_TEXTURECUBE - { - DDS_RESOURCE_MISC_TEXTURECUBE = 0x4, // Indicates a 2D texture is a cube-map texture. - }; - enum DDS_ALPHA_MODE - { - DDS_ALPHA_MODE_UNKNOWN = 0x0, // Alpha channel content is unknown. This is the value for legacy files, which typically is assumed to be 'straight' alpha. - DDS_ALPHA_MODE_STRAIGHT = 0x1, // Any alpha channel content is presumed to use straight alpha. - DDS_ALPHA_MODE_PREMULTIPLIED = 0x2, // Any alpha channel content is using premultiplied alpha. The only legacy file formats that indicate this information are 'DX2' and 'DX4'. - DDS_ALPHA_MODE_OPAQUE = 0x3, // Any alpha channel content is all set to fully opaque. - DDS_ALPHA_MODE_CUSTOM = 0x4, // Any alpha channel content is being used as a 4th channel and is not intended to represent transparency (straight or premultiplied). - }; - typedef struct { - DXGI_FORMAT dxgiFormat; - D3D10_RESOURCE_DIMENSION resourceDimension; - UINT miscFlag; - UINT arraySize; - UINT miscFlags2; - } DDS_HEADER_DXT10; - - static constexpr DWORD fourcc(char a, char b, char c, char d) - { - return (((unsigned)(d) << 24) | ((unsigned)(c) << 16) | ((unsigned)(b) << 8) | (unsigned)(a)); - } - - struct Header - { - DWORD magic; - DDS_HEADER header; - DDS_HEADER_DXT10 header10; - }; - - // Write the DDS header into memory. - // dst: destination file in memory, must be at least of sizeof(dds_write::Header) - // format: data format of texture data that will be placed after header - // width: width of top mip level - // height: height of top mip level (you can set this to 0 to indicate 1D texture) - // mip_levels: number of mip levels in the file - // array_size: number of slices in the file. For cubemaps, there is one slice for every face. For 3D texture, there is always only 1 slice. - // is_cubemap: whether the texture is a cubemap. If it is a cubemap, it must have at least array_size = 6 - // depth: depth of 3D texture (you can set this to 0 to indicate that the texture is not 3D) - inline void write_header( - void* dst, - DXGI_FORMAT format, - unsigned int width, - unsigned int height, - unsigned int mip_levels = 1, - unsigned int array_size = 1, - bool is_cubemap = false, - unsigned int depth = 0 - ) - { - Header h = {}; - h.magic = fourcc('D', 'D', 'S', ' '); - h.header.dwSize = sizeof(DDS_HEADER); - h.header.dwFlags = - DDSD_CAPS | - DDSD_WIDTH | - DDSD_HEIGHT | - DDSD_PIXELFORMAT | - DDSD_MIPMAPCOUNT - ; - h.header.dwWidth = width; - h.header.dwHeight = height; - h.header.dwDepth = depth; - h.header.dwMipMapCount = mip_levels; - h.header.ddspf.dwSize = sizeof(DDS_PIXELFORMAT); - h.header.ddspf.dwFlags = DDPF_FOURCC; - h.header.ddspf.dwFourCC = fourcc('D', 'X', '1', '0'); - h.header.dwCaps = DDSCAPS_TEXTURE; - - h.header10.dxgiFormat = format; - h.header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; - h.header10.miscFlags2 = DDS_ALPHA_MODE_UNKNOWN; - - if (is_cubemap) - { - h.header10.arraySize = array_size / 6; - h.header.dwCaps |= DDSCAPS_COMPLEX; - h.header.dwCaps2 = - DDSCAPS2_CUBEMAP | - DDSCAPS2_CUBEMAP_POSITIVEX | - DDSCAPS2_CUBEMAP_NEGATIVEX | - DDSCAPS2_CUBEMAP_POSITIVEY | - DDSCAPS2_CUBEMAP_NEGATIVEY | - DDSCAPS2_CUBEMAP_POSITIVEZ | - DDSCAPS2_CUBEMAP_NEGATIVEZ - ; - h.header10.miscFlag = DDS_RESOURCE_MISC_TEXTURECUBE; - } - else if (depth > 0) - { - h.header10.arraySize = 1; - h.header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D; - h.header.dwCaps2 = DDSCAPS2_VOLUME; - } - else - { - h.header10.arraySize = array_size; - } - - if (height == 0) - { - h.header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE1D; - h.header.dwHeight = 1; - } - if (mip_levels > 1) - { - h.header.dwCaps |= DDSCAPS_COMPLEX; - } - - *(Header*)dst = h; - } -} - -#endif // DDS_WRITE_H - -//Copyright(c) 2023 Turánszki János -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files(the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and /or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions : -// -//The above copyright notice and this permission notice shall be included in -//all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -//THE SOFTWARE. diff --git a/WickedEngine/Utility/tinyddsloader.h b/WickedEngine/Utility/tinyddsloader.h deleted file mode 100644 index 000cd5786..000000000 --- a/WickedEngine/Utility/tinyddsloader.h +++ /dev/null @@ -1,1161 +0,0 @@ -// -// Copyright(c) 2018 benikabocha. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) -// - -// Modified for Wicked Engine, DDS data is not copied internally, just memory mapped - -#ifndef TINYDDSLOADER_H_ -#define TINYDDSLOADER_H_ - -#include -#include - -namespace tinyddsloader { - -enum Result { - Success, - ErrorFileOpen, - ErrorRead, - ErrorMagicWord, - ErrorSize, - ErrorVerify, - ErrorNotSupported, - ErrorInvalidData, -}; - -class DDSFile { -public: - static const char Magic[4]; - - enum class PixelFormatFlagBits : uint32_t { - FourCC = 0x00000004, - RGB = 0x00000040, - RGBA = 0x00000041, - Luminance = 0x00020000, - LuminanceA = 0x00020001, - AlphaPixels = 0x00000001, - Alpha = 0x00000002, - Palette8 = 0x00000020, - Palette8A = 0x00000021, - BumpDUDV = 0x00080000 - }; - - enum class DXGIFormat : uint32_t { - Unknown = 0, - R32G32B32A32_Typeless = 1, - R32G32B32A32_Float = 2, - R32G32B32A32_UInt = 3, - R32G32B32A32_SInt = 4, - R32G32B32_Typeless = 5, - R32G32B32_Float = 6, - R32G32B32_UInt = 7, - R32G32B32_SInt = 8, - R16G16B16A16_Typeless = 9, - R16G16B16A16_Float = 10, - R16G16B16A16_UNorm = 11, - R16G16B16A16_UInt = 12, - R16G16B16A16_SNorm = 13, - R16G16B16A16_SInt = 14, - R32G32_Typeless = 15, - R32G32_Float = 16, - R32G32_UInt = 17, - R32G32_SInt = 18, - R32G8X24_Typeless = 19, - D32_Float_S8X24_UInt = 20, - R32_Float_X8X24_Typeless = 21, - X32_Typeless_G8X24_UInt = 22, - R10G10B10A2_Typeless = 23, - R10G10B10A2_UNorm = 24, - R10G10B10A2_UInt = 25, - R11G11B10_Float = 26, - R8G8B8A8_Typeless = 27, - R8G8B8A8_UNorm = 28, - R8G8B8A8_UNorm_SRGB = 29, - R8G8B8A8_UInt = 30, - R8G8B8A8_SNorm = 31, - R8G8B8A8_SInt = 32, - R16G16_Typeless = 33, - R16G16_Float = 34, - R16G16_UNorm = 35, - R16G16_UInt = 36, - R16G16_SNorm = 37, - R16G16_SInt = 38, - R32_Typeless = 39, - D32_Float = 40, - R32_Float = 41, - R32_UInt = 42, - R32_SInt = 43, - R24G8_Typeless = 44, - D24_UNorm_S8_UInt = 45, - R24_UNorm_X8_Typeless = 46, - X24_Typeless_G8_UInt = 47, - R8G8_Typeless = 48, - R8G8_UNorm = 49, - R8G8_UInt = 50, - R8G8_SNorm = 51, - R8G8_SInt = 52, - R16_Typeless = 53, - R16_Float = 54, - D16_UNorm = 55, - R16_UNorm = 56, - R16_UInt = 57, - R16_SNorm = 58, - R16_SInt = 59, - R8_Typeless = 60, - R8_UNorm = 61, - R8_UInt = 62, - R8_SNorm = 63, - R8_SInt = 64, - A8_UNorm = 65, - R1_UNorm = 66, - R9G9B9E5_SHAREDEXP = 67, - R8G8_B8G8_UNorm = 68, - G8R8_G8B8_UNorm = 69, - BC1_Typeless = 70, - BC1_UNorm = 71, - BC1_UNorm_SRGB = 72, - BC2_Typeless = 73, - BC2_UNorm = 74, - BC2_UNorm_SRGB = 75, - BC3_Typeless = 76, - BC3_UNorm = 77, - BC3_UNorm_SRGB = 78, - BC4_Typeless = 79, - BC4_UNorm = 80, - BC4_SNorm = 81, - BC5_Typeless = 82, - BC5_UNorm = 83, - BC5_SNorm = 84, - B5G6R5_UNorm = 85, - B5G5R5A1_UNorm = 86, - B8G8R8A8_UNorm = 87, - B8G8R8X8_UNorm = 88, - R10G10B10_XR_BIAS_A2_UNorm = 89, - B8G8R8A8_Typeless = 90, - B8G8R8A8_UNorm_SRGB = 91, - B8G8R8X8_Typeless = 92, - B8G8R8X8_UNorm_SRGB = 93, - BC6H_Typeless = 94, - BC6H_UF16 = 95, - BC6H_SF16 = 96, - BC7_Typeless = 97, - BC7_UNorm = 98, - BC7_UNorm_SRGB = 99, - AYUV = 100, - Y410 = 101, - Y416 = 102, - NV12 = 103, - P010 = 104, - P016 = 105, - YUV420_OPAQUE = 106, - YUY2 = 107, - Y210 = 108, - Y216 = 109, - NV11 = 110, - AI44 = 111, - IA44 = 112, - P8 = 113, - A8P8 = 114, - B4G4R4A4_UNorm = 115, - P208 = 130, - V208 = 131, - V408 = 132, - }; - - enum class HeaderFlagBits : uint32_t { - Height = 0x00000002, - Width = 0x00000004, - Texture = 0x00001007, - Mipmap = 0x00020000, - Volume = 0x00800000, - Pitch = 0x00000008, - LinearSize = 0x00080000, - }; - - enum class HeaderCaps2FlagBits : uint32_t { - CubemapPositiveX = 0x00000600, - CubemapNegativeX = 0x00000a00, - CubemapPositiveY = 0x00001200, - CubemapNegativeY = 0x00002200, - CubemapPositiveZ = 0x00004200, - CubemapNegativeZ = 0x00008200, - CubemapAllFaces = CubemapPositiveX | CubemapNegativeX | - CubemapPositiveY | CubemapNegativeY | - CubemapPositiveZ | CubemapNegativeZ, - Volume = 0x00200000, - }; - - struct PixelFormat { - uint32_t m_size; - uint32_t m_flags; - uint32_t m_fourCC; - uint32_t m_bitCount; - uint32_t m_RBitMask; - uint32_t m_GBitMask; - uint32_t m_BBitMask; - uint32_t m_ABitMask; - }; - - struct Header { - uint32_t m_size; - uint32_t m_flags; - uint32_t m_height; - uint32_t m_width; - uint32_t m_pitchOrLinerSize; - uint32_t m_depth; - uint32_t m_mipMapCount; - uint32_t m_reserved1[11]; - PixelFormat m_pixelFormat; - uint32_t m_caps; - uint32_t m_caps2; - uint32_t m_caps3; - uint32_t m_caps4; - uint32_t m_reserved2; - }; - - enum class TextureDimension : uint32_t { - Unknown = 0, - Texture1D = 2, - Texture2D = 3, - Texture3D = 4 - }; - - enum class DXT10MiscFlagBits : uint32_t { TextureCube = 0x4 }; - - struct HeaderDXT10 { - DXGIFormat m_format; - TextureDimension m_resourceDimension; - uint32_t m_miscFlag; - uint32_t m_arraySize; - uint32_t m_miscFlag2; - }; - - struct ImageData { - uint32_t m_width; - uint32_t m_height; - uint32_t m_depth; - const void* m_mem; - uint32_t m_memPitch; - uint32_t m_memSlicePitch; - }; - - struct BC1Block { - uint16_t m_color0; - uint16_t m_color1; - uint8_t m_row0; - uint8_t m_row1; - uint8_t m_row2; - uint8_t m_row3; - }; - - struct BC2Block { - uint16_t m_alphaRow0; - uint16_t m_alphaRow1; - uint16_t m_alphaRow2; - uint16_t m_alphaRow3; - uint16_t m_color0; - uint16_t m_color1; - uint8_t m_row0; - uint8_t m_row1; - uint8_t m_row2; - uint8_t m_row3; - }; - - struct BC3Block { - uint8_t m_alpha0; - uint8_t m_alpha1; - uint8_t m_alphaR0; - uint8_t m_alphaR1; - uint8_t m_alphaR2; - uint8_t m_alphaR3; - uint8_t m_alphaR4; - uint8_t m_alphaR5; - uint16_t m_color0; - uint16_t m_color1; - uint8_t m_row0; - uint8_t m_row1; - uint8_t m_row2; - uint8_t m_row3; - }; - -public: - static bool IsCompressed(DXGIFormat fmt); - static uint32_t MakeFourCC(char ch0, char ch1, char ch2, char ch3); - static DXGIFormat GetDXGIFormat(const PixelFormat& pf); - static uint32_t GetBitsPerPixel(DXGIFormat fmt); - - Result Load(const uint8_t* data, size_t size); - - const ImageData* GetImageData(uint32_t mipIdx = 0, - uint32_t arrayIdx = 0) const { - if (mipIdx < m_mipCount && arrayIdx < m_arraySize) { - return &m_imageDatas[m_mipCount * arrayIdx + mipIdx]; - } - return nullptr; - } - - bool Flip(); - - uint32_t GetWidth() const { return m_width; } - uint32_t GetHeight() const { return m_height; } - uint32_t GetDepth() const { return m_depth; } - uint32_t GetMipCount() const { return m_mipCount; } - uint32_t GetArraySize() const { return m_arraySize; } - DXGIFormat GetFormat() const { return m_format; } - bool IsCubemap() const { return m_isCubemap; } - TextureDimension GetTextureDimension() const { return m_texDim; } - -private: - void GetImageInfo(uint32_t w, uint32_t h, DXGIFormat fmt, - uint32_t* outNumBytes, uint32_t* outRowBytes, - uint32_t* outNumRows); - bool FlipImage(ImageData& imageData); - bool FlipCompressedImage(ImageData& imageData); - -private: - const uint8_t* m_dds = nullptr; - size_t m_dds_size = 0; - std::vector m_imageDatas; - - uint32_t m_height; - uint32_t m_width; - uint32_t m_depth; - uint32_t m_mipCount; - uint32_t m_arraySize; - DXGIFormat m_format; - bool m_isCubemap; - TextureDimension m_texDim; -}; - -} // namespace tinyddsloader - -#ifdef TINYDDSLOADER_IMPLEMENTATION - -#if _WIN32 -#undef min -#undef max -#endif // _Win32 - -#include -#include - -namespace tinyddsloader { - -const char DDSFile::Magic[4] = {'D', 'D', 'S', ' '}; - -bool DDSFile::IsCompressed(DXGIFormat fmt) { - switch (fmt) { - case DXGIFormat::BC1_Typeless: - case DXGIFormat::BC1_UNorm: - case DXGIFormat::BC1_UNorm_SRGB: - case DXGIFormat::BC2_Typeless: - case DXGIFormat::BC2_UNorm: - case DXGIFormat::BC2_UNorm_SRGB: - case DXGIFormat::BC3_Typeless: - case DXGIFormat::BC3_UNorm: - case DXGIFormat::BC3_UNorm_SRGB: - case DXGIFormat::BC4_Typeless: - case DXGIFormat::BC4_UNorm: - case DXGIFormat::BC4_SNorm: - case DXGIFormat::BC5_Typeless: - case DXGIFormat::BC5_UNorm: - case DXGIFormat::BC5_SNorm: - case DXGIFormat::BC6H_Typeless: - case DXGIFormat::BC6H_UF16: - case DXGIFormat::BC6H_SF16: - case DXGIFormat::BC7_Typeless: - case DXGIFormat::BC7_UNorm: - case DXGIFormat::BC7_UNorm_SRGB: - return true; - } - return false; -} - -uint32_t DDSFile::MakeFourCC(char ch0, char ch1, char ch2, char ch3) { - return (uint32_t(uint8_t(ch0)) | (uint32_t(uint8_t(ch1)) << 8) | - (uint32_t(uint8_t(ch2)) << 16) | (uint32_t(uint8_t(ch3)) << 24)); -} - -DDSFile::DXGIFormat DDSFile::GetDXGIFormat(const PixelFormat& pf) { - if (pf.m_flags & uint32_t(PixelFormatFlagBits::RGB)) { - switch (pf.m_bitCount) { - case 32: - if (pf.m_RBitMask == 0x000000ff && - pf.m_GBitMask == 0x0000ff00 && - pf.m_BBitMask == 0x00ff0000 && - pf.m_ABitMask == 0xff000000) { - return DXGIFormat::R8G8B8A8_UNorm; - } - if (pf.m_RBitMask == 0x00ff0000 && - pf.m_GBitMask == 0x0000ff00 && - pf.m_BBitMask == 0x000000ff && - pf.m_ABitMask == 0xff000000) { - return DXGIFormat::B8G8R8A8_UNorm; - } - if (pf.m_RBitMask == 0x00ff0000 && - pf.m_GBitMask == 0x0000ff00 && - pf.m_BBitMask == 0x000000ff && - pf.m_ABitMask == 0x00000000) { - return DXGIFormat::B8G8R8X8_UNorm; - } - - if (pf.m_RBitMask == 0x0000ffff && - pf.m_GBitMask == 0xffff0000 && - pf.m_BBitMask == 0x00000000 && - pf.m_ABitMask == 0x00000000) { - return DXGIFormat::R16G16_UNorm; - } - - if (pf.m_RBitMask == 0xffffffff && - pf.m_GBitMask == 0x00000000 && - pf.m_BBitMask == 0x00000000 && - pf.m_ABitMask == 0x00000000) { - return DXGIFormat::R32_Float; - } - break; - case 24: - break; - case 16: - if (pf.m_RBitMask == 0x7c00 && pf.m_GBitMask == 0x03e0 && - pf.m_BBitMask == 0x001f && pf.m_ABitMask == 0x8000) { - return DXGIFormat::B5G5R5A1_UNorm; - } - if (pf.m_RBitMask == 0xf800 && pf.m_GBitMask == 0x07e0 && - pf.m_BBitMask == 0x001f && pf.m_ABitMask == 0x0000) { - return DXGIFormat::B5G6R5_UNorm; - } - - if (pf.m_RBitMask == 0x0f00 && pf.m_GBitMask == 0x00f0 && - pf.m_BBitMask == 0x000f && pf.m_ABitMask == 0xf000) { - return DXGIFormat::B4G4R4A4_UNorm; - } - break; - default: - break; - } - } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::Luminance)) { - if (8 == pf.m_bitCount) { - if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x00000000 && - pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) { - return DXGIFormat::R8_UNorm; - } - if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x0000ff00 && - pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) { - return DXGIFormat::R8G8_UNorm; - } - } - if (16 == pf.m_bitCount) { - if (pf.m_RBitMask == 0x0000ffff && pf.m_GBitMask == 0x00000000 && - pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) { - return DXGIFormat::R16_UNorm; - } - if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x0000ff00 && - pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) { - return DXGIFormat::R8G8_UNorm; - } - } - } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::Alpha)) { - if (8 == pf.m_bitCount) { - return DXGIFormat::A8_UNorm; - } - } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::BumpDUDV)) { - if (16 == pf.m_bitCount) { - if (pf.m_RBitMask == 0x00ff && pf.m_GBitMask == 0xff00 && - pf.m_BBitMask == 0x0000 && pf.m_ABitMask == 0x0000) { - return DXGIFormat::R8G8_SNorm; - } - } - if (32 == pf.m_bitCount) { - if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x0000ff00 && - pf.m_BBitMask == 0x00ff0000 && pf.m_ABitMask == 0xff000000) { - return DXGIFormat::R8G8B8A8_SNorm; - } - if (pf.m_RBitMask == 0x0000ffff && pf.m_GBitMask == 0xffff0000 && - pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) { - return DXGIFormat::R16G16_SNorm; - } - } - } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::FourCC)) { - if (MakeFourCC('D', 'X', 'T', '1') == pf.m_fourCC) { - return DXGIFormat::BC1_UNorm; - } - if (MakeFourCC('D', 'X', 'T', '3') == pf.m_fourCC) { - return DXGIFormat::BC2_UNorm; - } - if (MakeFourCC('D', 'X', 'T', '5') == pf.m_fourCC) { - return DXGIFormat::BC3_UNorm; - } - - if (MakeFourCC('D', 'X', 'T', '4') == pf.m_fourCC) { - return DXGIFormat::BC2_UNorm; - } - if (MakeFourCC('D', 'X', 'T', '5') == pf.m_fourCC) { - return DXGIFormat::BC3_UNorm; - } - - if (MakeFourCC('A', 'T', 'I', '1') == pf.m_fourCC) { - return DXGIFormat::BC4_UNorm; - } - if (MakeFourCC('B', 'C', '4', 'U') == pf.m_fourCC) { - return DXGIFormat::BC4_UNorm; - } - if (MakeFourCC('B', 'C', '4', 'S') == pf.m_fourCC) { - return DXGIFormat::BC4_SNorm; - } - - if (MakeFourCC('A', 'T', 'I', '2') == pf.m_fourCC) { - return DXGIFormat::BC5_UNorm; - } - if (MakeFourCC('B', 'C', '5', 'U') == pf.m_fourCC) { - return DXGIFormat::BC5_UNorm; - } - if (MakeFourCC('B', 'C', '5', 'S') == pf.m_fourCC) { - return DXGIFormat::BC5_SNorm; - } - - if (MakeFourCC('R', 'G', 'B', 'G') == pf.m_fourCC) { - return DXGIFormat::R8G8_B8G8_UNorm; - } - if (MakeFourCC('G', 'R', 'G', 'B') == pf.m_fourCC) { - return DXGIFormat::G8R8_G8B8_UNorm; - } - - if (MakeFourCC('Y', 'U', 'Y', '2') == pf.m_fourCC) { - return DXGIFormat::YUY2; - } - - switch (pf.m_fourCC) { - case 36: - return DXGIFormat::R16G16B16A16_UNorm; - case 110: - return DXGIFormat::R16G16B16A16_SNorm; - case 111: - return DXGIFormat::R16_Float; - case 112: - return DXGIFormat::R16G16_Float; - case 113: - return DXGIFormat::R16G16B16A16_Float; - case 114: - return DXGIFormat::R32_Float; - case 115: - return DXGIFormat::R32G32_Float; - case 116: - return DXGIFormat::R32G32B32A32_Float; - } - } - - return DXGIFormat::Unknown; -} - -uint32_t DDSFile::GetBitsPerPixel(DXGIFormat fmt) { - switch (fmt) { - case DXGIFormat::R32G32B32A32_Typeless: - case DXGIFormat::R32G32B32A32_Float: - case DXGIFormat::R32G32B32A32_UInt: - case DXGIFormat::R32G32B32A32_SInt: - return 128; - - case DXGIFormat::R32G32B32_Typeless: - case DXGIFormat::R32G32B32_Float: - case DXGIFormat::R32G32B32_UInt: - case DXGIFormat::R32G32B32_SInt: - return 96; - - case DXGIFormat::R16G16B16A16_Typeless: - case DXGIFormat::R16G16B16A16_Float: - case DXGIFormat::R16G16B16A16_UNorm: - case DXGIFormat::R16G16B16A16_UInt: - case DXGIFormat::R16G16B16A16_SNorm: - case DXGIFormat::R16G16B16A16_SInt: - case DXGIFormat::R32G32_Typeless: - case DXGIFormat::R32G32_Float: - case DXGIFormat::R32G32_UInt: - case DXGIFormat::R32G32_SInt: - case DXGIFormat::R32G8X24_Typeless: - case DXGIFormat::D32_Float_S8X24_UInt: - case DXGIFormat::R32_Float_X8X24_Typeless: - case DXGIFormat::X32_Typeless_G8X24_UInt: - case DXGIFormat::Y416: - case DXGIFormat::Y210: - case DXGIFormat::Y216: - return 64; - - case DXGIFormat::R10G10B10A2_Typeless: - case DXGIFormat::R10G10B10A2_UNorm: - case DXGIFormat::R10G10B10A2_UInt: - case DXGIFormat::R11G11B10_Float: - case DXGIFormat::R8G8B8A8_Typeless: - case DXGIFormat::R8G8B8A8_UNorm: - case DXGIFormat::R8G8B8A8_UNorm_SRGB: - case DXGIFormat::R8G8B8A8_UInt: - case DXGIFormat::R8G8B8A8_SNorm: - case DXGIFormat::R8G8B8A8_SInt: - case DXGIFormat::R16G16_Typeless: - case DXGIFormat::R16G16_Float: - case DXGIFormat::R16G16_UNorm: - case DXGIFormat::R16G16_UInt: - case DXGIFormat::R16G16_SNorm: - case DXGIFormat::R16G16_SInt: - case DXGIFormat::R32_Typeless: - case DXGIFormat::D32_Float: - case DXGIFormat::R32_Float: - case DXGIFormat::R32_UInt: - case DXGIFormat::R32_SInt: - case DXGIFormat::R24G8_Typeless: - case DXGIFormat::D24_UNorm_S8_UInt: - case DXGIFormat::R24_UNorm_X8_Typeless: - case DXGIFormat::X24_Typeless_G8_UInt: - case DXGIFormat::R9G9B9E5_SHAREDEXP: - case DXGIFormat::R8G8_B8G8_UNorm: - case DXGIFormat::G8R8_G8B8_UNorm: - case DXGIFormat::B8G8R8A8_UNorm: - case DXGIFormat::B8G8R8X8_UNorm: - case DXGIFormat::R10G10B10_XR_BIAS_A2_UNorm: - case DXGIFormat::B8G8R8A8_Typeless: - case DXGIFormat::B8G8R8A8_UNorm_SRGB: - case DXGIFormat::B8G8R8X8_Typeless: - case DXGIFormat::B8G8R8X8_UNorm_SRGB: - case DXGIFormat::AYUV: - case DXGIFormat::Y410: - case DXGIFormat::YUY2: - return 32; - - case DXGIFormat::P010: - case DXGIFormat::P016: - return 24; - - case DXGIFormat::R8G8_Typeless: - case DXGIFormat::R8G8_UNorm: - case DXGIFormat::R8G8_UInt: - case DXGIFormat::R8G8_SNorm: - case DXGIFormat::R8G8_SInt: - case DXGIFormat::R16_Typeless: - case DXGIFormat::R16_Float: - case DXGIFormat::D16_UNorm: - case DXGIFormat::R16_UNorm: - case DXGIFormat::R16_UInt: - case DXGIFormat::R16_SNorm: - case DXGIFormat::R16_SInt: - case DXGIFormat::B5G6R5_UNorm: - case DXGIFormat::B5G5R5A1_UNorm: - case DXGIFormat::A8P8: - case DXGIFormat::B4G4R4A4_UNorm: - return 16; - - case DXGIFormat::NV12: - case DXGIFormat::YUV420_OPAQUE: - case DXGIFormat::NV11: - return 12; - - case DXGIFormat::R8_Typeless: - case DXGIFormat::R8_UNorm: - case DXGIFormat::R8_UInt: - case DXGIFormat::R8_SNorm: - case DXGIFormat::R8_SInt: - case DXGIFormat::A8_UNorm: - case DXGIFormat::AI44: - case DXGIFormat::IA44: - case DXGIFormat::P8: - return 8; - - case DXGIFormat::R1_UNorm: - return 1; - - case DXGIFormat::BC1_Typeless: - case DXGIFormat::BC1_UNorm: - case DXGIFormat::BC1_UNorm_SRGB: - case DXGIFormat::BC4_Typeless: - case DXGIFormat::BC4_UNorm: - case DXGIFormat::BC4_SNorm: - return 4; - - case DXGIFormat::BC2_Typeless: - case DXGIFormat::BC2_UNorm: - case DXGIFormat::BC2_UNorm_SRGB: - case DXGIFormat::BC3_Typeless: - case DXGIFormat::BC3_UNorm: - case DXGIFormat::BC3_UNorm_SRGB: - case DXGIFormat::BC5_Typeless: - case DXGIFormat::BC5_UNorm: - case DXGIFormat::BC5_SNorm: - case DXGIFormat::BC6H_Typeless: - case DXGIFormat::BC6H_UF16: - case DXGIFormat::BC6H_SF16: - case DXGIFormat::BC7_Typeless: - case DXGIFormat::BC7_UNorm: - case DXGIFormat::BC7_UNorm_SRGB: - return 8; - default: - return 0; - } -} - -Result DDSFile::Load(const uint8_t* dds_data, size_t dds_size) { - - if (dds_size < 4) { - return Result::ErrorSize; - } - - for (int i = 0; i < 4; i++) { - if (dds_data[i] != Magic[i]) { - return Result::ErrorMagicWord; - } - } - - if ((sizeof(uint32_t) + sizeof(Header)) >= dds_size) { - return Result::ErrorSize; - } - auto header = - reinterpret_cast(dds_data + sizeof(uint32_t)); - - if (header->m_size != sizeof(Header) || - header->m_pixelFormat.m_size != sizeof(PixelFormat)) { - return Result::ErrorVerify; - } - bool dxt10Header = false; - if ((header->m_pixelFormat.m_flags & - uint32_t(PixelFormatFlagBits::FourCC)) && - (MakeFourCC('D', 'X', '1', '0') == header->m_pixelFormat.m_fourCC)) { - if ((sizeof(uint32_t) + sizeof(Header) + sizeof(HeaderDXT10)) >= - dds_size) { - return Result::ErrorSize; - } - dxt10Header = true; - } - ptrdiff_t offset = sizeof(uint32_t) + sizeof(Header) + - (dxt10Header ? sizeof(HeaderDXT10) : 0); - - m_height = header->m_height; - m_width = header->m_width; - m_texDim = TextureDimension::Unknown; - m_arraySize = 1; - m_format = DXGIFormat::Unknown; - m_isCubemap = false; - m_mipCount = header->m_mipMapCount; - if (0 == m_mipCount) { - m_mipCount = 1; - } - - if (dxt10Header) { - auto dxt10Header = reinterpret_cast( - reinterpret_cast(header) + sizeof(Header)); - - m_arraySize = dxt10Header->m_arraySize; - if (m_arraySize == 0) { - return Result::ErrorInvalidData; - } - - switch (dxt10Header->m_format) { - case DXGIFormat::AI44: - case DXGIFormat::IA44: - case DXGIFormat::P8: - case DXGIFormat::A8P8: - return Result::ErrorNotSupported; - default: - if (GetBitsPerPixel(dxt10Header->m_format) == 0) { - return Result::ErrorNotSupported; - } - } - - m_format = dxt10Header->m_format; - - switch (dxt10Header->m_resourceDimension) { - case TextureDimension::Texture1D: - if ((header->m_flags & uint32_t(HeaderFlagBits::Height) && - (m_height != 1))) { - return Result::ErrorInvalidData; - } - m_height = m_depth = 1; - break; - case TextureDimension::Texture2D: - if (dxt10Header->m_miscFlag & - uint32_t(DXT10MiscFlagBits::TextureCube)) { - m_arraySize *= 6; - m_isCubemap = true; - } - m_depth = 1; - break; - case TextureDimension::Texture3D: - if (!(header->m_flags & uint32_t(HeaderFlagBits::Volume))) { - return Result::ErrorInvalidData; - } - if (m_arraySize > 1) { - return Result::ErrorNotSupported; - } - break; - default: - return Result::ErrorNotSupported; - } - - m_texDim = dxt10Header->m_resourceDimension; - } else { - m_format = GetDXGIFormat(header->m_pixelFormat); - if (m_format == DXGIFormat::Unknown) { - return Result::ErrorNotSupported; - } - - if (header->m_flags & uint32_t(HeaderFlagBits::Volume)) { - m_texDim = TextureDimension::Texture3D; - } else { - auto caps2 = header->m_caps2 & - uint32_t(HeaderCaps2FlagBits::CubemapAllFaces); - if (caps2) { - if (caps2 != uint32_t(HeaderCaps2FlagBits::CubemapAllFaces)) { - return Result::ErrorNotSupported; - } - m_arraySize = 6; - m_isCubemap = true; - } - - m_depth = 1; - m_texDim = TextureDimension::Texture2D; - } - } - - std::vector imageDatas(m_mipCount * m_arraySize); - const uint8_t* srcBits = dds_data + offset; - const uint8_t* endBits = dds_data + dds_size; - uint32_t idx = 0; - for (uint32_t j = 0; j < m_arraySize; j++) { - uint32_t w = m_width; - uint32_t h = m_height; - uint32_t d = m_depth; - for (uint32_t i = 0; i < m_mipCount; i++) { - uint32_t numBytes; - uint32_t rowBytes; - GetImageInfo(w, h, m_format, &numBytes, &rowBytes, nullptr); - - imageDatas[idx].m_width = w; - imageDatas[idx].m_height = h; - imageDatas[idx].m_depth = d; - imageDatas[idx].m_mem = srcBits; - imageDatas[idx].m_memPitch = rowBytes; - imageDatas[idx].m_memSlicePitch = numBytes; - idx++; - - if (srcBits + (numBytes * d) > endBits) { - return Result::ErrorInvalidData; - } - srcBits += numBytes * d; - w = std::max(1, w / 2); - h = std::max(1, h / 2); - d = std::max(1, d / 2); - } - } - - m_dds = dds_data; - m_dds_size = dds_size; - m_imageDatas = std::move(imageDatas); - - return Result::Success; -} - -void DDSFile::GetImageInfo(uint32_t w, uint32_t h, DXGIFormat fmt, - uint32_t* outNumBytes, uint32_t* outRowBytes, - uint32_t* outNumRows) { - uint32_t numBytes = 0; - uint32_t rowBytes = 0; - uint32_t numRows = 0; - - bool bc = false; - bool packed = false; - bool planar = false; - uint32_t bpe = 0; - switch (fmt) { - case DXGIFormat::BC1_Typeless: - case DXGIFormat::BC1_UNorm: - case DXGIFormat::BC1_UNorm_SRGB: - case DXGIFormat::BC4_Typeless: - case DXGIFormat::BC4_UNorm: - case DXGIFormat::BC4_SNorm: - bc = true; - bpe = 8; - break; - - case DXGIFormat::BC2_Typeless: - case DXGIFormat::BC2_UNorm: - case DXGIFormat::BC2_UNorm_SRGB: - case DXGIFormat::BC3_Typeless: - case DXGIFormat::BC3_UNorm: - case DXGIFormat::BC3_UNorm_SRGB: - case DXGIFormat::BC5_Typeless: - case DXGIFormat::BC5_UNorm: - case DXGIFormat::BC5_SNorm: - case DXGIFormat::BC6H_Typeless: - case DXGIFormat::BC6H_UF16: - case DXGIFormat::BC6H_SF16: - case DXGIFormat::BC7_Typeless: - case DXGIFormat::BC7_UNorm: - case DXGIFormat::BC7_UNorm_SRGB: - bc = true; - bpe = 16; - break; - - case DXGIFormat::R8G8_B8G8_UNorm: - case DXGIFormat::G8R8_G8B8_UNorm: - case DXGIFormat::YUY2: - packed = true; - bpe = 4; - break; - - case DXGIFormat::Y210: - case DXGIFormat::Y216: - packed = true; - bpe = 8; - break; - - case DXGIFormat::NV12: - case DXGIFormat::YUV420_OPAQUE: - planar = true; - bpe = 2; - break; - - case DXGIFormat::P010: - case DXGIFormat::P016: - planar = true; - bpe = 4; - break; - default: - break; - } - - if (bc) { - uint32_t numBlocksWide = 0; - if (w > 0) { - numBlocksWide = std::max(1, (w + 3) / 4); - } - uint32_t numBlocksHigh = 0; - if (h > 0) { - numBlocksHigh = std::max(1, (h + 3) / 4); - } - rowBytes = numBlocksWide * bpe; - numRows = numBlocksHigh; - numBytes = rowBytes * numBlocksHigh; - } else if (packed) { - rowBytes = ((w + 1) >> 1) * bpe; - numRows = h; - numBytes = rowBytes * h; - } else if (fmt == DXGIFormat::NV11) { - rowBytes = ((w + 3) >> 2) * 4; - numRows = h * 2; - numBytes = rowBytes + numRows; - } else if (planar) { - rowBytes = ((w + 1) >> 1) * bpe; - numBytes = (rowBytes * h) + ((rowBytes * h + 1) >> 1); - numRows = h + ((h + 1) >> 1); - } else { - uint32_t bpp = GetBitsPerPixel(fmt); - rowBytes = (w * bpp + 7) / 8; - numRows = h; - numBytes = rowBytes * h; - } - - if (outNumBytes) { - *outNumBytes = numBytes; - } - if (outRowBytes) { - *outRowBytes = rowBytes; - } - if (outNumRows) { - *outNumRows = numRows; - } -} - -bool DDSFile::Flip() { - if (IsCompressed(m_format)) { - for (auto& imageData : m_imageDatas) { - if (!FlipCompressedImage(imageData)) { - return false; - } - } - } else { - for (auto& imageData : m_imageDatas) { - if (!FlipImage(imageData)) { - return false; - } - } - } - return true; -} - -bool DDSFile::FlipImage(ImageData& imageData) { - for (uint32_t y = 0; y < imageData.m_height / 2; y++) { - auto line0 = (uint8_t*)imageData.m_mem + y * imageData.m_memPitch; - auto line1 = (uint8_t*)imageData.m_mem + - (imageData.m_height - y - 1) * imageData.m_memPitch; - for (uint32_t i = 0; i < imageData.m_memPitch; i++) { - std::swap(*line0, *line1); - line0++; - line1++; - } - } - return true; -} - -bool DDSFile::FlipCompressedImage(ImageData& imageData) { - if (DXGIFormat::BC1_Typeless == m_format || - DXGIFormat::BC1_UNorm == m_format || - DXGIFormat::BC1_UNorm_SRGB == m_format) { - uint32_t numXBlocks = (imageData.m_width + 3) / 4; - uint32_t numYBlocks = (imageData.m_height + 3) / 4; - if (imageData.m_height == 1) { - return true; - } else if (imageData.m_height == 2) { - auto blocks = (BC1Block*)imageData.m_mem; - for (uint32_t x = 0; x < numXBlocks; x++) { - auto block = blocks + x; - std::swap(block->m_row0, block->m_row1); - std::swap(block->m_row2, block->m_row3); - } - return true; - } else { - for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) { - auto blocks0 = (BC1Block*)((uint8_t*)imageData.m_mem + - imageData.m_memPitch * y); - auto blocks1 = - (BC1Block*)((uint8_t*)imageData.m_mem + - imageData.m_memPitch * (numYBlocks - y - 1)); - for (uint32_t x = 0; x < numXBlocks; x++) { - auto block0 = blocks0 + x; - auto block1 = blocks1 + x; - std::swap(block0->m_color0, block1->m_color0); - std::swap(block0->m_color1, block1->m_color1); - std::swap(block0->m_row0, block1->m_row3); - std::swap(block0->m_row1, block1->m_row2); - std::swap(block0->m_row2, block1->m_row1); - std::swap(block0->m_row3, block1->m_row0); - } - } - return true; - } - } else if (DXGIFormat::BC2_Typeless == m_format || - DXGIFormat::BC2_UNorm == m_format || - DXGIFormat::BC2_UNorm_SRGB == m_format) { - uint32_t numXBlocks = (imageData.m_width + 3) / 4; - uint32_t numYBlocks = (imageData.m_height + 3) / 4; - if (imageData.m_height == 1) { - return true; - } else if (imageData.m_height == 2) { - auto blocks = (BC2Block*)imageData.m_mem; - for (uint32_t x = 0; x < numXBlocks; x++) { - auto block = blocks + x; - std::swap(block->m_alphaRow0, block->m_alphaRow1); - std::swap(block->m_alphaRow2, block->m_alphaRow3); - std::swap(block->m_row0, block->m_row1); - std::swap(block->m_row2, block->m_row3); - } - return true; - } else { - for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) { - auto blocks0 = (BC2Block*)((uint8_t*)imageData.m_mem + - imageData.m_memPitch * y); - auto blocks1 = - (BC2Block*)((uint8_t*)imageData.m_mem + - imageData.m_memPitch * (numYBlocks - y - 1)); - for (uint32_t x = 0; x < numXBlocks; x++) { - auto block0 = blocks0 + x; - auto block1 = blocks1 + x; - std::swap(block0->m_alphaRow0, block1->m_alphaRow3); - std::swap(block0->m_alphaRow1, block1->m_alphaRow2); - std::swap(block0->m_alphaRow2, block1->m_alphaRow1); - std::swap(block0->m_alphaRow3, block1->m_alphaRow0); - std::swap(block0->m_color0, block1->m_color0); - std::swap(block0->m_color1, block1->m_color1); - std::swap(block0->m_row0, block1->m_row3); - std::swap(block0->m_row1, block1->m_row2); - std::swap(block0->m_row2, block1->m_row1); - std::swap(block0->m_row3, block1->m_row0); - } - } - return true; - } - } else if (DXGIFormat::BC3_Typeless == m_format || - DXGIFormat::BC3_UNorm == m_format || - DXGIFormat::BC3_UNorm_SRGB == m_format) { - uint32_t numXBlocks = (imageData.m_width + 3) / 4; - uint32_t numYBlocks = (imageData.m_height + 3) / 4; - if (imageData.m_height == 1) { - return true; - } else if (imageData.m_height == 2) { - auto blocks = (BC3Block*)imageData.m_mem; - for (uint32_t x = 0; x < numXBlocks; x++) { - auto block = blocks + x; - uint8_t r0 = (block->m_alphaR1 >> 4) | (block->m_alphaR2 << 4); - uint8_t r1 = (block->m_alphaR2 >> 4) | (block->m_alphaR0 << 4); - uint8_t r2 = (block->m_alphaR0 >> 4) | (block->m_alphaR1 << 4); - uint8_t r3 = (block->m_alphaR4 >> 4) | (block->m_alphaR5 << 4); - uint8_t r4 = (block->m_alphaR5 >> 4) | (block->m_alphaR3 << 4); - uint8_t r5 = (block->m_alphaR3 >> 4) | (block->m_alphaR4 << 4); - - block->m_alphaR0 = r0; - block->m_alphaR1 = r1; - block->m_alphaR2 = r2; - block->m_alphaR3 = r3; - block->m_alphaR4 = r4; - block->m_alphaR5 = r5; - std::swap(block->m_row0, block->m_row1); - std::swap(block->m_row2, block->m_row3); - } - return true; - } else { - for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) { - auto blocks0 = (BC3Block*)((uint8_t*)imageData.m_mem + - imageData.m_memPitch * y); - auto blocks1 = - (BC3Block*)((uint8_t*)imageData.m_mem + - imageData.m_memPitch * (numYBlocks - y - 1)); - for (uint32_t x = 0; x < numXBlocks; x++) { - auto block0 = blocks0 + x; - auto block1 = blocks1 + x; - std::swap(block0->m_alpha0, block1->m_alpha0); - std::swap(block0->m_alpha1, block1->m_alpha1); - - uint8_t r0[6]; - r0[0] = (block0->m_alphaR4 >> 4) | (block0->m_alphaR5 << 4); - r0[1] = (block0->m_alphaR5 >> 4) | (block0->m_alphaR3 << 4); - r0[2] = (block0->m_alphaR3 >> 4) | (block0->m_alphaR4 << 4); - r0[3] = (block0->m_alphaR1 >> 4) | (block0->m_alphaR2 << 4); - r0[4] = (block0->m_alphaR2 >> 4) | (block0->m_alphaR0 << 4); - r0[5] = (block0->m_alphaR0 >> 4) | (block0->m_alphaR1 << 4); - uint8_t r1[6]; - r1[0] = (block1->m_alphaR4 >> 4) | (block1->m_alphaR5 << 4); - r1[1] = (block1->m_alphaR5 >> 4) | (block1->m_alphaR3 << 4); - r1[2] = (block1->m_alphaR3 >> 4) | (block1->m_alphaR4 << 4); - r1[3] = (block1->m_alphaR1 >> 4) | (block1->m_alphaR2 << 4); - r1[4] = (block1->m_alphaR2 >> 4) | (block1->m_alphaR0 << 4); - r1[5] = (block1->m_alphaR0 >> 4) | (block1->m_alphaR1 << 4); - - block0->m_alphaR0 = r1[0]; - block0->m_alphaR1 = r1[1]; - block0->m_alphaR2 = r1[2]; - block0->m_alphaR3 = r1[3]; - block0->m_alphaR4 = r1[4]; - block0->m_alphaR5 = r1[5]; - - block1->m_alphaR0 = r0[0]; - block1->m_alphaR1 = r0[1]; - block1->m_alphaR2 = r0[2]; - block1->m_alphaR3 = r0[3]; - block1->m_alphaR4 = r0[4]; - block1->m_alphaR5 = r0[5]; - - std::swap(block0->m_color0, block1->m_color0); - std::swap(block0->m_color1, block1->m_color1); - std::swap(block0->m_row0, block1->m_row3); - std::swap(block0->m_row1, block1->m_row2); - std::swap(block0->m_row2, block1->m_row1); - std::swap(block0->m_row3, block1->m_row0); - } - } - return true; - } - } - return false; -} - -} // namespace tinyddsloader - -#endif // !TINYDDSLOADER_IMPLEMENTATION - -#endif // !TINYDDSLOADER_H_ diff --git a/WickedEngine/Utility/utility_common.cpp b/WickedEngine/Utility/utility_common.cpp index 7533703eb..266f3e426 100644 --- a/WickedEngine/Utility/utility_common.cpp +++ b/WickedEngine/Utility/utility_common.cpp @@ -15,9 +15,6 @@ #define STB_TRUETYPE_IMPLEMENTATION #include "stb_truetype.h" -#define TINYDDSLOADER_IMPLEMENTATION -#include "tinyddsloader.h" - #define QOI_IMPLEMENTATION #include "qoi.h" diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems b/WickedEngine/WickedEngine_SOURCE.vcxitems index 6043968e6..d1ed10bf8 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems @@ -229,7 +229,7 @@ - + @@ -264,7 +264,6 @@ - diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters index 8cd627ced..5db17e374 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters @@ -972,9 +972,6 @@ ENGINE\Network - - UTILITY - UTILITY @@ -1119,7 +1116,7 @@ UTILITY - + UTILITY diff --git a/WickedEngine/wiHelper.cpp b/WickedEngine/wiHelper.cpp index 3f4e2d544..a1ffa0954 100644 --- a/WickedEngine/wiHelper.cpp +++ b/WickedEngine/wiHelper.cpp @@ -5,7 +5,7 @@ #include "wiMath.h" #include "Utility/lodepng.h" -#include "Utility/dds_write.h" +#include "Utility/dds.h" #include "Utility/stb_image_write.h" #include "Utility/basis_universal/encoder/basisu_comp.h" #include "Utility/basis_universal/encoder/basisu_gpu_texture.h" @@ -229,197 +229,197 @@ namespace wi::helper if (extension.compare("DDS") == 0) { - filedata.resize(sizeof(dds_write::Header) + texturedata.size()); - dds_write::DXGI_FORMAT dds_format = dds_write::DXGI_FORMAT_UNKNOWN; + filedata.resize(sizeof(dds::Header) + texturedata.size()); + dds::DXGI_FORMAT dds_format = dds::DXGI_FORMAT_UNKNOWN; switch (desc.format) { case wi::graphics::Format::R32G32B32A32_FLOAT: - dds_format = dds_write::DXGI_FORMAT_R32G32B32A32_FLOAT; + dds_format = dds::DXGI_FORMAT_R32G32B32A32_FLOAT; break; case wi::graphics::Format::R32G32B32A32_UINT: - dds_format = dds_write::DXGI_FORMAT_R32G32B32A32_UINT; + dds_format = dds::DXGI_FORMAT_R32G32B32A32_UINT; break; case wi::graphics::Format::R32G32B32A32_SINT: - dds_format = dds_write::DXGI_FORMAT_R32G32B32A32_SINT; + dds_format = dds::DXGI_FORMAT_R32G32B32A32_SINT; break; case wi::graphics::Format::R32G32B32_FLOAT: - dds_format = dds_write::DXGI_FORMAT_R32G32B32_FLOAT; + dds_format = dds::DXGI_FORMAT_R32G32B32_FLOAT; break; case wi::graphics::Format::R32G32B32_UINT: - dds_format = dds_write::DXGI_FORMAT_R32G32B32_UINT; + dds_format = dds::DXGI_FORMAT_R32G32B32_UINT; break; case wi::graphics::Format::R32G32B32_SINT: - dds_format = dds_write::DXGI_FORMAT_R32G32B32_SINT; + dds_format = dds::DXGI_FORMAT_R32G32B32_SINT; break; case wi::graphics::Format::R16G16B16A16_FLOAT: - dds_format = dds_write::DXGI_FORMAT_R16G16B16A16_FLOAT; + dds_format = dds::DXGI_FORMAT_R16G16B16A16_FLOAT; break; case wi::graphics::Format::R16G16B16A16_UNORM: - dds_format = dds_write::DXGI_FORMAT_R16G16B16A16_UNORM; + dds_format = dds::DXGI_FORMAT_R16G16B16A16_UNORM; break; case wi::graphics::Format::R16G16B16A16_UINT: - dds_format = dds_write::DXGI_FORMAT_R16G16B16A16_UINT; + dds_format = dds::DXGI_FORMAT_R16G16B16A16_UINT; break; case wi::graphics::Format::R16G16B16A16_SNORM: - dds_format = dds_write::DXGI_FORMAT_R16G16B16A16_SNORM; + dds_format = dds::DXGI_FORMAT_R16G16B16A16_SNORM; break; case wi::graphics::Format::R16G16B16A16_SINT: - dds_format = dds_write::DXGI_FORMAT_R16G16B16A16_SINT; + dds_format = dds::DXGI_FORMAT_R16G16B16A16_SINT; break; case wi::graphics::Format::R32G32_FLOAT: - dds_format = dds_write::DXGI_FORMAT_R32G32_FLOAT; + dds_format = dds::DXGI_FORMAT_R32G32_FLOAT; break; case wi::graphics::Format::R32G32_UINT: - dds_format = dds_write::DXGI_FORMAT_R32G32_UINT; + dds_format = dds::DXGI_FORMAT_R32G32_UINT; break; case wi::graphics::Format::R32G32_SINT: - dds_format = dds_write::DXGI_FORMAT_R32G32_SINT; + dds_format = dds::DXGI_FORMAT_R32G32_SINT; break; case wi::graphics::Format::R10G10B10A2_UNORM: - dds_format = dds_write::DXGI_FORMAT_R10G10B10A2_UNORM; + dds_format = dds::DXGI_FORMAT_R10G10B10A2_UNORM; break; case wi::graphics::Format::R10G10B10A2_UINT: - dds_format = dds_write::DXGI_FORMAT_R10G10B10A2_UINT; + dds_format = dds::DXGI_FORMAT_R10G10B10A2_UINT; break; case wi::graphics::Format::R11G11B10_FLOAT: - dds_format = dds_write::DXGI_FORMAT_R11G11B10_FLOAT; + dds_format = dds::DXGI_FORMAT_R11G11B10_FLOAT; break; case wi::graphics::Format::R8G8B8A8_UNORM: - dds_format = dds_write::DXGI_FORMAT_R8G8B8A8_UNORM; + dds_format = dds::DXGI_FORMAT_R8G8B8A8_UNORM; break; case wi::graphics::Format::R8G8B8A8_UNORM_SRGB: - dds_format = dds_write::DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + dds_format = dds::DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; break; case wi::graphics::Format::R8G8B8A8_UINT: - dds_format = dds_write::DXGI_FORMAT_R8G8B8A8_UINT; + dds_format = dds::DXGI_FORMAT_R8G8B8A8_UINT; break; case wi::graphics::Format::R8G8B8A8_SNORM: - dds_format = dds_write::DXGI_FORMAT_R8G8B8A8_SNORM; + dds_format = dds::DXGI_FORMAT_R8G8B8A8_SNORM; break; case wi::graphics::Format::R8G8B8A8_SINT: - dds_format = dds_write::DXGI_FORMAT_R8G8B8A8_SINT; + dds_format = dds::DXGI_FORMAT_R8G8B8A8_SINT; break; case wi::graphics::Format::B8G8R8A8_UNORM: - dds_format = dds_write::DXGI_FORMAT_B8G8R8A8_UNORM; + dds_format = dds::DXGI_FORMAT_B8G8R8A8_UNORM; break; case wi::graphics::Format::B8G8R8A8_UNORM_SRGB: - dds_format = dds_write::DXGI_FORMAT_R16G16_SINT; + dds_format = dds::DXGI_FORMAT_R16G16_SINT; break; case wi::graphics::Format::R16G16_FLOAT: - dds_format = dds_write::DXGI_FORMAT_R16G16_FLOAT; + dds_format = dds::DXGI_FORMAT_R16G16_FLOAT; break; case wi::graphics::Format::R16G16_UNORM: - dds_format = dds_write::DXGI_FORMAT_R16G16_UNORM; + dds_format = dds::DXGI_FORMAT_R16G16_UNORM; break; case wi::graphics::Format::R16G16_UINT: - dds_format = dds_write::DXGI_FORMAT_R16G16_UINT; + dds_format = dds::DXGI_FORMAT_R16G16_UINT; break; case wi::graphics::Format::R16G16_SNORM: - dds_format = dds_write::DXGI_FORMAT_R16G16_SNORM; + dds_format = dds::DXGI_FORMAT_R16G16_SNORM; break; case wi::graphics::Format::R16G16_SINT: - dds_format = dds_write::DXGI_FORMAT_R16G16_SINT; + dds_format = dds::DXGI_FORMAT_R16G16_SINT; break; case wi::graphics::Format::D32_FLOAT: case wi::graphics::Format::R32_FLOAT: - dds_format = dds_write::DXGI_FORMAT_R32_FLOAT; + dds_format = dds::DXGI_FORMAT_R32_FLOAT; break; case wi::graphics::Format::R32_UINT: - dds_format = dds_write::DXGI_FORMAT_R32_UINT; + dds_format = dds::DXGI_FORMAT_R32_UINT; break; case wi::graphics::Format::R32_SINT: - dds_format = dds_write::DXGI_FORMAT_R32_SINT; + dds_format = dds::DXGI_FORMAT_R32_SINT; break; case wi::graphics::Format::R9G9B9E5_SHAREDEXP: - dds_format = dds_write::DXGI_FORMAT_R9G9B9E5_SHAREDEXP; + dds_format = dds::DXGI_FORMAT_R9G9B9E5_SHAREDEXP; break; case wi::graphics::Format::R8G8_UNORM: - dds_format = dds_write::DXGI_FORMAT_R8G8_UNORM; + dds_format = dds::DXGI_FORMAT_R8G8_UNORM; break; case wi::graphics::Format::R8G8_UINT: - dds_format = dds_write::DXGI_FORMAT_R8G8_UINT; + dds_format = dds::DXGI_FORMAT_R8G8_UINT; break; case wi::graphics::Format::R8G8_SNORM: - dds_format = dds_write::DXGI_FORMAT_R8G8_SNORM; + dds_format = dds::DXGI_FORMAT_R8G8_SNORM; break; case wi::graphics::Format::R8G8_SINT: - dds_format = dds_write::DXGI_FORMAT_R8G8_SINT; + dds_format = dds::DXGI_FORMAT_R8G8_SINT; break; case wi::graphics::Format::R16_FLOAT: - dds_format = dds_write::DXGI_FORMAT_R16_FLOAT; + dds_format = dds::DXGI_FORMAT_R16_FLOAT; break; case wi::graphics::Format::D16_UNORM: case wi::graphics::Format::R16_UNORM: - dds_format = dds_write::DXGI_FORMAT_R16_UNORM; + dds_format = dds::DXGI_FORMAT_R16_UNORM; break; case wi::graphics::Format::R16_UINT: - dds_format = dds_write::DXGI_FORMAT_R16_UINT; + dds_format = dds::DXGI_FORMAT_R16_UINT; break; case wi::graphics::Format::R16_SNORM: - dds_format = dds_write::DXGI_FORMAT_R16_SNORM; + dds_format = dds::DXGI_FORMAT_R16_SNORM; break; case wi::graphics::Format::R16_SINT: - dds_format = dds_write::DXGI_FORMAT_R16_SINT; + dds_format = dds::DXGI_FORMAT_R16_SINT; break; case wi::graphics::Format::R8_UNORM: - dds_format = dds_write::DXGI_FORMAT_R8_UNORM; + dds_format = dds::DXGI_FORMAT_R8_UNORM; break; case wi::graphics::Format::R8_UINT: - dds_format = dds_write::DXGI_FORMAT_R8_UINT; + dds_format = dds::DXGI_FORMAT_R8_UINT; break; case wi::graphics::Format::R8_SNORM: - dds_format = dds_write::DXGI_FORMAT_R8_SNORM; + dds_format = dds::DXGI_FORMAT_R8_SNORM; break; case wi::graphics::Format::R8_SINT: - dds_format = dds_write::DXGI_FORMAT_R8_SINT; + dds_format = dds::DXGI_FORMAT_R8_SINT; break; case wi::graphics::Format::BC1_UNORM: - dds_format = dds_write::DXGI_FORMAT_BC1_UNORM; + dds_format = dds::DXGI_FORMAT_BC1_UNORM; break; case wi::graphics::Format::BC1_UNORM_SRGB: - dds_format = dds_write::DXGI_FORMAT_BC1_UNORM_SRGB; + dds_format = dds::DXGI_FORMAT_BC1_UNORM_SRGB; break; case wi::graphics::Format::BC2_UNORM: - dds_format = dds_write::DXGI_FORMAT_BC2_UNORM; + dds_format = dds::DXGI_FORMAT_BC2_UNORM; break; case wi::graphics::Format::BC2_UNORM_SRGB: - dds_format = dds_write::DXGI_FORMAT_BC2_UNORM_SRGB; + dds_format = dds::DXGI_FORMAT_BC2_UNORM_SRGB; break; case wi::graphics::Format::BC3_UNORM: - dds_format = dds_write::DXGI_FORMAT_BC3_UNORM; + dds_format = dds::DXGI_FORMAT_BC3_UNORM; break; case wi::graphics::Format::BC3_UNORM_SRGB: - dds_format = dds_write::DXGI_FORMAT_BC3_UNORM_SRGB; + dds_format = dds::DXGI_FORMAT_BC3_UNORM_SRGB; break; case wi::graphics::Format::BC4_UNORM: - dds_format = dds_write::DXGI_FORMAT_BC4_UNORM; + dds_format = dds::DXGI_FORMAT_BC4_UNORM; break; case wi::graphics::Format::BC4_SNORM: - dds_format = dds_write::DXGI_FORMAT_BC4_SNORM; + dds_format = dds::DXGI_FORMAT_BC4_SNORM; break; case wi::graphics::Format::BC5_UNORM: - dds_format = dds_write::DXGI_FORMAT_BC5_UNORM; + dds_format = dds::DXGI_FORMAT_BC5_UNORM; break; case wi::graphics::Format::BC5_SNORM: - dds_format = dds_write::DXGI_FORMAT_BC5_SNORM; + dds_format = dds::DXGI_FORMAT_BC5_SNORM; break; case wi::graphics::Format::BC6H_UF16: - dds_format = dds_write::DXGI_FORMAT_BC6H_UF16; + dds_format = dds::DXGI_FORMAT_BC6H_UF16; break; case wi::graphics::Format::BC6H_SF16: - dds_format = dds_write::DXGI_FORMAT_BC6H_SF16; + dds_format = dds::DXGI_FORMAT_BC6H_SF16; break; case wi::graphics::Format::BC7_UNORM: - dds_format = dds_write::DXGI_FORMAT_BC7_UNORM; + dds_format = dds::DXGI_FORMAT_BC7_UNORM; break; case wi::graphics::Format::BC7_UNORM_SRGB: - dds_format = dds_write::DXGI_FORMAT_BC7_UNORM_SRGB; + dds_format = dds::DXGI_FORMAT_BC7_UNORM_SRGB; break; default: assert(0); return false; } - dds_write::write_header( + dds::write_header( filedata.data(), dds_format, desc.width, @@ -429,7 +429,7 @@ namespace wi::helper has_flag(desc.misc_flags, ResourceMiscFlag::TEXTURECUBE), desc.type == TextureDesc::Type::TEXTURE_3D ? desc.depth : 0 ); - std::memcpy(filedata.data() + sizeof(dds_write::Header), texturedata.data(), texturedata.size()); + std::memcpy(filedata.data() + sizeof(dds::Header), texturedata.data(), texturedata.size()); return true; } diff --git a/WickedEngine/wiResourceManager.cpp b/WickedEngine/wiResourceManager.cpp index dd0372cce..309b7c0c8 100644 --- a/WickedEngine/wiResourceManager.cpp +++ b/WickedEngine/wiResourceManager.cpp @@ -8,8 +8,8 @@ #include "Utility/qoi.h" #include "Utility/stb_image.h" -#include "Utility/tinyddsloader.h" #include "Utility/basis_universal/transcoder/basisu_transcoder.h" +#include "Utility/dds.h" #include #include @@ -657,24 +657,22 @@ namespace wi } else if (!ext.compare("DDS")) { - tinyddsloader::DDSFile dds; - auto result = dds.Load(filedata, filesize); - - if (result == tinyddsloader::Result::Success) + dds::Header header = dds::read_header(filedata, filesize); + if (header.is_valid()) { TextureDesc desc; desc.array_size = 1; desc.bind_flags = BindFlag::SHADER_RESOURCE; - desc.width = dds.GetWidth(); - desc.height = dds.GetHeight(); - desc.depth = dds.GetDepth(); - desc.mip_levels = dds.GetMipCount(); - desc.array_size = dds.GetArraySize(); + desc.width = header.width(); + desc.height = header.height(); + desc.depth = header.depth(); + desc.mip_levels = header.mip_levels(); + desc.array_size = header.array_size(); desc.format = Format::R8G8B8A8_UNORM; desc.layout = ResourceState::SHADER_RESOURCE; desc.misc_flags = ResourceMiscFlag::TYPED_FORMAT_CASTING; - if (dds.IsCubemap()) + if (header.is_cubemap()) { desc.misc_flags |= ResourceMiscFlag::TEXTURECUBE; } @@ -684,73 +682,73 @@ namespace wi flags &= ~Flags::STREAMING; } - auto ddsFormat = dds.GetFormat(); + auto ddsFormat = header.format(); switch (ddsFormat) { - case tinyddsloader::DDSFile::DXGIFormat::R32G32B32A32_Float: desc.format = Format::R32G32B32A32_FLOAT; break; - case tinyddsloader::DDSFile::DXGIFormat::R32G32B32A32_UInt: desc.format = Format::R32G32B32A32_UINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R32G32B32A32_SInt: desc.format = Format::R32G32B32A32_SINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R32G32B32_Float: desc.format = Format::R32G32B32_FLOAT; break; - case tinyddsloader::DDSFile::DXGIFormat::R32G32B32_UInt: desc.format = Format::R32G32B32_UINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R32G32B32_SInt: desc.format = Format::R32G32B32_SINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R16G16B16A16_Float: desc.format = Format::R16G16B16A16_FLOAT; break; - case tinyddsloader::DDSFile::DXGIFormat::R16G16B16A16_UNorm: desc.format = Format::R16G16B16A16_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R16G16B16A16_UInt: desc.format = Format::R16G16B16A16_UINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R16G16B16A16_SNorm: desc.format = Format::R16G16B16A16_SNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R16G16B16A16_SInt: desc.format = Format::R16G16B16A16_SINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R32G32_Float: desc.format = Format::R32G32_FLOAT; break; - case tinyddsloader::DDSFile::DXGIFormat::R32G32_UInt: desc.format = Format::R32G32_UINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R32G32_SInt: desc.format = Format::R32G32_SINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R10G10B10A2_UNorm: desc.format = Format::R10G10B10A2_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R10G10B10A2_UInt: desc.format = Format::R10G10B10A2_UINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R11G11B10_Float: desc.format = Format::R11G11B10_FLOAT; break; - case tinyddsloader::DDSFile::DXGIFormat::R9G9B9E5_SHAREDEXP: desc.format = Format::R9G9B9E5_SHAREDEXP; break; - case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm: desc.format = Format::B8G8R8A8_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm: desc.format = Format::B8G8R8A8_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB: desc.format = Format::B8G8R8A8_UNORM_SRGB; break; - case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm: desc.format = Format::R8G8B8A8_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB: desc.format = Format::R8G8B8A8_UNORM_SRGB; break; - case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UInt: desc.format = Format::R8G8B8A8_UINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SNorm: desc.format = Format::R8G8B8A8_SNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SInt: desc.format = Format::R8G8B8A8_SINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R16G16_Float: desc.format = Format::R16G16_FLOAT; break; - case tinyddsloader::DDSFile::DXGIFormat::R16G16_UNorm: desc.format = Format::R16G16_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R16G16_UInt: desc.format = Format::R16G16_UINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R16G16_SNorm: desc.format = Format::R16G16_SNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R16G16_SInt: desc.format = Format::R16G16_SINT; break; - case tinyddsloader::DDSFile::DXGIFormat::D32_Float: desc.format = Format::D32_FLOAT; break; - case tinyddsloader::DDSFile::DXGIFormat::R32_Float: desc.format = Format::R32_FLOAT; break; - case tinyddsloader::DDSFile::DXGIFormat::R32_UInt: desc.format = Format::R32_UINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R32_SInt: desc.format = Format::R32_SINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R8G8_UNorm: desc.format = Format::R8G8_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R8G8_UInt: desc.format = Format::R8G8_UINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R8G8_SNorm: desc.format = Format::R8G8_SNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R8G8_SInt: desc.format = Format::R8G8_SINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R16_Float: desc.format = Format::R16_FLOAT; break; - case tinyddsloader::DDSFile::DXGIFormat::D16_UNorm: desc.format = Format::D16_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R16_UNorm: desc.format = Format::R16_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R16_UInt: desc.format = Format::R16_UINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R16_SNorm: desc.format = Format::R16_SNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R16_SInt: desc.format = Format::R16_SINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R8_UNorm: desc.format = Format::R8_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R8_UInt: desc.format = Format::R8_UINT; break; - case tinyddsloader::DDSFile::DXGIFormat::R8_SNorm: desc.format = Format::R8_SNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::R8_SInt: desc.format = Format::R8_SINT; break; - case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm: desc.format = Format::BC1_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB: desc.format = Format::BC1_UNORM_SRGB; break; - case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm: desc.format = Format::BC2_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB: desc.format = Format::BC2_UNORM_SRGB; break; - case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm: desc.format = Format::BC3_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB: desc.format = Format::BC3_UNORM_SRGB; break; - case tinyddsloader::DDSFile::DXGIFormat::BC4_UNorm: desc.format = Format::BC4_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::BC4_SNorm: desc.format = Format::BC4_SNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm: desc.format = Format::BC5_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::BC5_SNorm: desc.format = Format::BC5_SNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::BC6H_SF16: desc.format = Format::BC6H_SF16; break; - case tinyddsloader::DDSFile::DXGIFormat::BC6H_UF16: desc.format = Format::BC6H_UF16; break; - case tinyddsloader::DDSFile::DXGIFormat::BC7_UNorm: desc.format = Format::BC7_UNORM; break; - case tinyddsloader::DDSFile::DXGIFormat::BC7_UNorm_SRGB: desc.format = Format::BC7_UNORM_SRGB; break; + case dds::DXGI_FORMAT_R32G32B32A32_FLOAT: desc.format = Format::R32G32B32A32_FLOAT; break; + case dds::DXGI_FORMAT_R32G32B32A32_UINT: desc.format = Format::R32G32B32A32_UINT; break; + case dds::DXGI_FORMAT_R32G32B32A32_SINT: desc.format = Format::R32G32B32A32_SINT; break; + case dds::DXGI_FORMAT_R32G32B32_FLOAT: desc.format = Format::R32G32B32_FLOAT; break; + case dds::DXGI_FORMAT_R32G32B32_UINT: desc.format = Format::R32G32B32_UINT; break; + case dds::DXGI_FORMAT_R32G32B32_SINT: desc.format = Format::R32G32B32_SINT; break; + case dds::DXGI_FORMAT_R16G16B16A16_FLOAT: desc.format = Format::R16G16B16A16_FLOAT; break; + case dds::DXGI_FORMAT_R16G16B16A16_UNORM: desc.format = Format::R16G16B16A16_UNORM; break; + case dds::DXGI_FORMAT_R16G16B16A16_UINT: desc.format = Format::R16G16B16A16_UINT; break; + case dds::DXGI_FORMAT_R16G16B16A16_SNORM: desc.format = Format::R16G16B16A16_SNORM; break; + case dds::DXGI_FORMAT_R16G16B16A16_SINT: desc.format = Format::R16G16B16A16_SINT; break; + case dds::DXGI_FORMAT_R32G32_FLOAT: desc.format = Format::R32G32_FLOAT; break; + case dds::DXGI_FORMAT_R32G32_UINT: desc.format = Format::R32G32_UINT; break; + case dds::DXGI_FORMAT_R32G32_SINT: desc.format = Format::R32G32_SINT; break; + case dds::DXGI_FORMAT_R10G10B10A2_UNORM: desc.format = Format::R10G10B10A2_UNORM; break; + case dds::DXGI_FORMAT_R10G10B10A2_UINT: desc.format = Format::R10G10B10A2_UINT; break; + case dds::DXGI_FORMAT_R11G11B10_FLOAT: desc.format = Format::R11G11B10_FLOAT; break; + case dds::DXGI_FORMAT_R9G9B9E5_SHAREDEXP: desc.format = Format::R9G9B9E5_SHAREDEXP; break; + case dds::DXGI_FORMAT_B8G8R8X8_UNORM: desc.format = Format::B8G8R8A8_UNORM; break; + case dds::DXGI_FORMAT_B8G8R8A8_UNORM: desc.format = Format::B8G8R8A8_UNORM; break; + case dds::DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: desc.format = Format::B8G8R8A8_UNORM_SRGB; break; + case dds::DXGI_FORMAT_R8G8B8A8_UNORM: desc.format = Format::R8G8B8A8_UNORM; break; + case dds::DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: desc.format = Format::R8G8B8A8_UNORM_SRGB; break; + case dds::DXGI_FORMAT_R8G8B8A8_UINT: desc.format = Format::R8G8B8A8_UINT; break; + case dds::DXGI_FORMAT_R8G8B8A8_SNORM: desc.format = Format::R8G8B8A8_SNORM; break; + case dds::DXGI_FORMAT_R8G8B8A8_SINT: desc.format = Format::R8G8B8A8_SINT; break; + case dds::DXGI_FORMAT_R16G16_FLOAT: desc.format = Format::R16G16_FLOAT; break; + case dds::DXGI_FORMAT_R16G16_UNORM: desc.format = Format::R16G16_UNORM; break; + case dds::DXGI_FORMAT_R16G16_UINT: desc.format = Format::R16G16_UINT; break; + case dds::DXGI_FORMAT_R16G16_SNORM: desc.format = Format::R16G16_SNORM; break; + case dds::DXGI_FORMAT_R16G16_SINT: desc.format = Format::R16G16_SINT; break; + case dds::DXGI_FORMAT_D32_FLOAT: desc.format = Format::D32_FLOAT; break; + case dds::DXGI_FORMAT_R32_FLOAT: desc.format = Format::R32_FLOAT; break; + case dds::DXGI_FORMAT_R32_UINT: desc.format = Format::R32_UINT; break; + case dds::DXGI_FORMAT_R32_SINT: desc.format = Format::R32_SINT; break; + case dds::DXGI_FORMAT_R8G8_UNORM: desc.format = Format::R8G8_UNORM; break; + case dds::DXGI_FORMAT_R8G8_UINT: desc.format = Format::R8G8_UINT; break; + case dds::DXGI_FORMAT_R8G8_SNORM: desc.format = Format::R8G8_SNORM; break; + case dds::DXGI_FORMAT_R8G8_SINT: desc.format = Format::R8G8_SINT; break; + case dds::DXGI_FORMAT_R16_FLOAT: desc.format = Format::R16_FLOAT; break; + case dds::DXGI_FORMAT_D16_UNORM: desc.format = Format::D16_UNORM; break; + case dds::DXGI_FORMAT_R16_UNORM: desc.format = Format::R16_UNORM; break; + case dds::DXGI_FORMAT_R16_UINT: desc.format = Format::R16_UINT; break; + case dds::DXGI_FORMAT_R16_SNORM: desc.format = Format::R16_SNORM; break; + case dds::DXGI_FORMAT_R16_SINT: desc.format = Format::R16_SINT; break; + case dds::DXGI_FORMAT_R8_UNORM: desc.format = Format::R8_UNORM; break; + case dds::DXGI_FORMAT_R8_UINT: desc.format = Format::R8_UINT; break; + case dds::DXGI_FORMAT_R8_SNORM: desc.format = Format::R8_SNORM; break; + case dds::DXGI_FORMAT_R8_SINT: desc.format = Format::R8_SINT; break; + case dds::DXGI_FORMAT_BC1_UNORM: desc.format = Format::BC1_UNORM; break; + case dds::DXGI_FORMAT_BC1_UNORM_SRGB: desc.format = Format::BC1_UNORM_SRGB; break; + case dds::DXGI_FORMAT_BC2_UNORM: desc.format = Format::BC2_UNORM; break; + case dds::DXGI_FORMAT_BC2_UNORM_SRGB: desc.format = Format::BC2_UNORM_SRGB; break; + case dds::DXGI_FORMAT_BC3_UNORM: desc.format = Format::BC3_UNORM; break; + case dds::DXGI_FORMAT_BC3_UNORM_SRGB: desc.format = Format::BC3_UNORM_SRGB; break; + case dds::DXGI_FORMAT_BC4_UNORM: desc.format = Format::BC4_UNORM; break; + case dds::DXGI_FORMAT_BC4_SNORM: desc.format = Format::BC4_SNORM; break; + case dds::DXGI_FORMAT_BC5_UNORM: desc.format = Format::BC5_UNORM; break; + case dds::DXGI_FORMAT_BC5_SNORM: desc.format = Format::BC5_SNORM; break; + case dds::DXGI_FORMAT_BC6H_SF16: desc.format = Format::BC6H_SF16; break; + case dds::DXGI_FORMAT_BC6H_UF16: desc.format = Format::BC6H_UF16; break; + case dds::DXGI_FORMAT_BC7_UNORM: desc.format = Format::BC7_UNORM; break; + case dds::DXGI_FORMAT_BC7_UNORM_SRGB: desc.format = Format::BC7_UNORM_SRGB; break; default: assert(0); // incoming format is not supported break; @@ -766,49 +764,25 @@ namespace wi wi::vector initdata; initdata.reserve(desc.array_size * desc.mip_levels); - for (uint32_t arrayIndex = 0; arrayIndex < desc.array_size; ++arrayIndex) + for (uint32_t slice = 0; slice < desc.array_size; ++slice) { for (uint32_t mip = 0; mip < desc.mip_levels; ++mip) { - auto imageData = dds.GetImageData(mip, arrayIndex); SubresourceData& subresourceData = initdata.emplace_back(); - subresourceData.data_ptr = imageData->m_mem; - subresourceData.row_pitch = imageData->m_memPitch; - subresourceData.slice_pitch = imageData->m_memSlicePitch; - - if (has_flag(flags, Flags::STREAMING)) - { - // For streaming, remember relative memory offsets for mip levels: - auto& streaming_data = resource->streaming_texture.streaming_data[mip]; - streaming_data.data_offset = (size_t)subresourceData.data_ptr - (size_t)filedata; - streaming_data.row_pitch = subresourceData.row_pitch; - streaming_data.slice_pitch = subresourceData.slice_pitch; - } + subresourceData.data_ptr = filedata + header.mip_offset(mip, slice); + subresourceData.row_pitch = header.row_pitch(mip); + subresourceData.slice_pitch = header.slice_pitch(mip); } } - auto dim = dds.GetTextureDimension(); - switch (dim) - { - case tinyddsloader::DDSFile::TextureDimension::Texture1D: + if (header.is_1d()) { desc.type = TextureDesc::Type::TEXTURE_1D; } - break; - case tinyddsloader::DDSFile::TextureDimension::Texture2D: - { - desc.type = TextureDesc::Type::TEXTURE_2D; - } - break; - case tinyddsloader::DDSFile::TextureDimension::Texture3D: + else if (header.is_3d()) { desc.type = TextureDesc::Type::TEXTURE_3D; } - break; - default: - assert(0); - break; - } if (IsFormatBlockCompressed(desc.format)) { @@ -820,6 +794,17 @@ namespace wi int mip_offset = 0; if (has_flag(flags, Flags::STREAMING)) { + // For streaming, remember relative memory offsets for mip levels: + for (uint32_t slice = 0; slice < desc.array_size; ++slice) + { + for (uint32_t mip = 0; mip < desc.mip_levels; ++mip) + { + auto& streaming_data = resource->streaming_texture.streaming_data[mip]; + streaming_data.data_offset = header.mip_offset(mip, slice); + streaming_data.row_pitch = header.row_pitch(mip); + streaming_data.slice_pitch = header.slice_pitch(mip); + } + } while (desc.mip_levels > 1 && desc.depth == 1 && desc.array_size == 1 && ComputeTextureMemorySizeInBytes(desc) > streaming_texture_min_size) { desc.width >>= 1; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index b2cbd75bc..80d2297f0 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 473; + const int revision = 474; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision); diff --git a/third_party_software.txt b/third_party_software.txt index aec1b68a7..a1c1e8ecb 100644 --- a/third_party_software.txt +++ b/third_party_software.txt @@ -133,32 +133,6 @@ THE SOFTWARE. ############################################################################################################################### -benikabocha/tinyddsloader: https://github.com/benikabocha/tinyddsloader - -The MIT License (MIT) - -Copyright (c) 2018 benikabocha - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -############################################################################################################################### - Vulkan Memory Allocator: https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator The MIT License (MIT)