From 1c471913188594d622ebe274fe7471b9c51aa0d1 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Mon, 19 Aug 2024 16:27:36 -0700 Subject: [PATCH] Xbox auxiliary EncodeDDSHeader helper exposed as public function (#497) --- Auxiliary/DirectXTexEXR.cpp | 2 +- Auxiliary/DirectXTexXbox.h | 52 ++--- Auxiliary/DirectXTexXboxD3D11X.cpp | 2 +- Auxiliary/DirectXTexXboxD3D12X.cpp | 2 +- Auxiliary/DirectXTexXboxDDS.cpp | 319 +++++++++++++---------------- CMakeLists.txt | 2 +- DirectXTex/DDS.h | 69 +++++-- DirectXTex/DirectXTexDDS.cpp | 40 ++-- Texconv/PortablePixMap.cpp | 3 +- build/CompilerAndLinker.cmake | 30 ++- 10 files changed, 282 insertions(+), 239 deletions(-) diff --git a/Auxiliary/DirectXTexEXR.cpp b/Auxiliary/DirectXTexEXR.cpp index cd4655b2..16aa31f3 100644 --- a/Auxiliary/DirectXTexEXR.cpp +++ b/Auxiliary/DirectXTexEXR.cpp @@ -410,7 +410,7 @@ HRESULT DirectX::LoadFromEXRFile(const wchar_t* szFile, TexMetadata* metadata, S hr = image.Initialize2D(DXGI_FORMAT_R16G16B16A16_FLOAT, static_cast(width), static_cast(height), arraySize, 1u); - + if (FAILED(hr)) return hr; diff --git a/Auxiliary/DirectXTexXbox.h b/Auxiliary/DirectXTexXbox.h index 4e283938..4aa5f741 100644 --- a/Auxiliary/DirectXTexXbox.h +++ b/Auxiliary/DirectXTexXbox.h @@ -69,12 +69,12 @@ namespace Xbox XboxImage(const XboxImage&) = delete; XboxImage& operator=(const XboxImage&) = delete; - HRESULT Initialize(_In_ const XG_TEXTURE1D_DESC& desc, _In_ const XG_RESOURCE_LAYOUT& layout, _In_ uint32_t miscFlags2 = 0); - HRESULT Initialize(_In_ const XG_TEXTURE2D_DESC& desc, _In_ const XG_RESOURCE_LAYOUT& layout, _In_ uint32_t miscFlags2 = 0); - HRESULT Initialize(_In_ const XG_TEXTURE3D_DESC& desc, _In_ const XG_RESOURCE_LAYOUT& layout, _In_ uint32_t miscFlags2 = 0); - HRESULT Initialize(_In_ const DirectX::TexMetadata& mdata, _In_ XboxTileMode tm, _In_ uint32_t size, _In_ uint32_t alignment); + HRESULT __cdecl Initialize(_In_ const XG_TEXTURE1D_DESC& desc, _In_ const XG_RESOURCE_LAYOUT& layout, _In_ uint32_t miscFlags2 = 0); + HRESULT __cdecl Initialize(_In_ const XG_TEXTURE2D_DESC& desc, _In_ const XG_RESOURCE_LAYOUT& layout, _In_ uint32_t miscFlags2 = 0); + HRESULT __cdecl Initialize(_In_ const XG_TEXTURE3D_DESC& desc, _In_ const XG_RESOURCE_LAYOUT& layout, _In_ uint32_t miscFlags2 = 0); + HRESULT __cdecl Initialize(_In_ const DirectX::TexMetadata& mdata, _In_ XboxTileMode tm, _In_ uint32_t size, _In_ uint32_t alignment); - void Release(); + void __cdecl Release(); const DirectX::TexMetadata& GetMetadata() const { return metadata; } XboxTileMode GetTileMode() const { return tilemode; } @@ -94,65 +94,65 @@ namespace Xbox //--------------------------------------------------------------------------------- // Image I/O - HRESULT GetMetadataFromDDSMemory( + HRESULT __cdecl GetMetadataFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _Out_ DirectX::TexMetadata& metadata, _Out_ bool& isXbox); - HRESULT GetMetadataFromDDSFile( + HRESULT __cdecl GetMetadataFromDDSFile( _In_z_ const wchar_t* szFile, _Out_ DirectX::TexMetadata& metadata, _Out_ bool& isXbox); - HRESULT GetMetadataFromDDSMemoryEx( + HRESULT __cdecl GetMetadataFromDDSMemoryEx( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _Out_ DirectX::TexMetadata& metadata, _Out_ bool& isXbox, _Out_opt_ DirectX::DDSMetaData* ddPixelFormat); - HRESULT GetMetadataFromDDSFileEx( + HRESULT __cdecl GetMetadataFromDDSFileEx( _In_z_ const wchar_t* szFile, _Out_ DirectX::TexMetadata& metadata, _Out_ bool& isXbox, _Out_opt_ DirectX::DDSMetaData* ddPixelFormat); - HRESULT LoadFromDDSMemory( + HRESULT __cdecl LoadFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _Out_opt_ DirectX::TexMetadata* metadata, _Out_ XboxImage& image); - HRESULT LoadFromDDSFile( + HRESULT __cdecl LoadFromDDSFile( _In_z_ const wchar_t* szFile, _Out_opt_ DirectX::TexMetadata* metadata, _Out_ XboxImage& image); - HRESULT LoadFromDDSMemoryEx( + HRESULT __cdecl LoadFromDDSMemoryEx( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _Out_opt_ DirectX::TexMetadata* metadata, _Out_opt_ DirectX::DDSMetaData* ddPixelFormat, _Out_ XboxImage& image); - HRESULT LoadFromDDSFileEx( + HRESULT __cdecl LoadFromDDSFileEx( _In_z_ const wchar_t* szFile, _Out_opt_ DirectX::TexMetadata* metadata, _Out_opt_ DirectX::DDSMetaData* ddPixelFormat, _Out_ XboxImage& image); - HRESULT SaveToDDSMemory(_In_ const XboxImage& xbox, _Out_ DirectX::Blob& blob); - HRESULT SaveToDDSFile(_In_ const XboxImage& xbox, _In_z_ const wchar_t* szFile); + HRESULT __cdecl SaveToDDSMemory(_In_ const XboxImage& xbox, _Out_ DirectX::Blob& blob); + HRESULT __cdecl SaveToDDSFile(_In_ const XboxImage& xbox, _In_z_ const wchar_t* szFile); //--------------------------------------------------------------------------------- // Xbox Texture Tiling / Detiling (requires XG DLL to be present at runtime) - HRESULT Tile(_In_ const DirectX::Image& srcImage, _Out_ XboxImage& xbox, _In_ XboxTileMode mode = c_XboxTileModeInvalid); - HRESULT Tile( + HRESULT __cdecl Tile(_In_ const DirectX::Image& srcImage, _Out_ XboxImage& xbox, _In_ XboxTileMode mode = c_XboxTileModeInvalid); + HRESULT __cdecl Tile( _In_ const DirectX::Image* srcImages, _In_ size_t nimages, _In_ const DirectX::TexMetadata& metadata, _Out_ XboxImage& xbox, _In_ XboxTileMode mode = c_XboxTileModeInvalid); - HRESULT Detile(_In_ const XboxImage& xbox, _Out_ DirectX::ScratchImage& image); + HRESULT __cdecl Detile(_In_ const XboxImage& xbox, _Out_ DirectX::ScratchImage& image); //--------------------------------------------------------------------------------- // Direct3D 11.X functions #if defined(_XBOX_ONE) && defined(_TITLE) && defined(__d3d11_x_h__) - HRESULT CreateTexture( + HRESULT __cdecl CreateTexture( _In_ ID3D11DeviceX* d3dDevice, _In_ const XboxImage& xbox, _Outptr_opt_ ID3D11Resource** ppResource, _Outptr_ void** grfxMemory); - HRESULT CreateShaderResourceView( + HRESULT __cdecl CreateShaderResourceView( _In_ ID3D11DeviceX* d3dDevice, _In_ const XboxImage& xbox, _Outptr_opt_ ID3D11ShaderResourceView** ppSRV, _Outptr_ void** grfxMemory); - void FreeTextureMemory(_In_ ID3D11DeviceX* d3dDevice, _In_opt_ void* grfxMemory); + void __cdecl FreeTextureMemory(_In_ ID3D11DeviceX* d3dDevice, _In_opt_ void* grfxMemory); #endif @@ -161,12 +161,18 @@ namespace Xbox #if ((defined(_XBOX_ONE) && defined(_TITLE)) || defined(_GAMING_XBOX)) && (defined(__d3d12_x_h__) || defined(__XBOX_D3D12_X__)) - HRESULT CreateTexture( + HRESULT __cdecl CreateTexture( _In_ ID3D12Device* d3dDevice, _In_ const XboxImage& xbox, _Outptr_opt_ ID3D12Resource** ppResource, _Outptr_ void** grfxMemory); - void FreeTextureMemory(_In_ ID3D12Device* d3dDevice, _In_opt_ void* grfxMemory); + void __cdecl FreeTextureMemory(_In_ ID3D12Device* d3dDevice, _In_opt_ void* grfxMemory); #endif + //--------------------------------------------------------------------------------- + // DDS helper functions + HRESULT __cdecl EncodeDDSHeader( + const XboxImage& xbox, + _Out_writes_bytes_(maxsize) void* pDestination, _In_ size_t maxsize) noexcept; + } // namespace diff --git a/Auxiliary/DirectXTexXboxD3D11X.cpp b/Auxiliary/DirectXTexXboxD3D11X.cpp index d511bc5a..b95c8cfa 100644 --- a/Auxiliary/DirectXTexXboxD3D11X.cpp +++ b/Auxiliary/DirectXTexXboxD3D11X.cpp @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------------- // DirectXTexD3D11X.cpp -// +// // DirectXTex Auxilary functions for creating resouces from XboxImage containers // via the CreatePlacement APIs // diff --git a/Auxiliary/DirectXTexXboxD3D12X.cpp b/Auxiliary/DirectXTexXboxD3D12X.cpp index dba250e6..63e8534e 100644 --- a/Auxiliary/DirectXTexXboxD3D12X.cpp +++ b/Auxiliary/DirectXTexXboxD3D12X.cpp @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------------- // DirectXTexD3D12X.cpp -// +// // DirectXTex Auxilary functions for creating resouces from XboxImage containers // via the CreatePlacedResourceX API // diff --git a/Auxiliary/DirectXTexXboxDDS.cpp b/Auxiliary/DirectXTexXboxDDS.cpp index 91657573..8158f083 100644 --- a/Auxiliary/DirectXTexXboxDDS.cpp +++ b/Auxiliary/DirectXTexXboxDDS.cpp @@ -23,34 +23,6 @@ using namespace Xbox; namespace { - const DDS_PIXELFORMAT DDSPF_XBOX = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('X','B','O','X'), 0, 0, 0, 0, 0 }; - -#pragma pack(push,1) - - struct DDS_HEADER_XBOX - // Must match structure in XboxDDSTextureLoader module - { - DXGI_FORMAT dxgiFormat; - uint32_t resourceDimension; - uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG - uint32_t arraySize; - uint32_t miscFlags2; // see DDS_MISC_FLAGS2 - uint32_t tileMode; // see XG_TILE_MODE / XG_SWIZZLE_MODE - uint32_t baseAlignment; - uint32_t dataSize; - uint32_t xdkVer; // matching _XDK_VER / _GXDK_VER - }; - -#pragma pack(pop) - - constexpr uint32_t XBOX_TILEMODE_SCARLETT = 0x1000000; - - static_assert(sizeof(DDS_HEADER_XBOX) == 36, "DDS XBOX Header size mismatch"); - static_assert(sizeof(DDS_HEADER_XBOX) >= sizeof(DDS_HEADER_DXT10), "DDS XBOX Header should be larger than DX10 header"); - - constexpr size_t XBOX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_XBOX); - //------------------------------------------------------------------------------------- // Decodes DDS header using XBOX extended header (variant of DX10 header) //------------------------------------------------------------------------------------- @@ -86,7 +58,7 @@ namespace *ddPixelFormat = {}; } - if (size < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + if (size < DDS_MIN_HEADER_SIZE) { return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); } @@ -120,13 +92,13 @@ namespace } // Buffer must be big enough for both headers and magic value - if (size < XBOX_HEADER_SIZE) + if (size < DDS_XBOX_HEADER_SIZE) { return E_FAIL; } auto xboxext = reinterpret_cast( - reinterpret_cast(pSource) + sizeof(uint32_t) + sizeof(DDS_HEADER)); + reinterpret_cast(pSource) + DDS_MIN_HEADER_SIZE); metadata.arraySize = xboxext->arraySize; if (metadata.arraySize == 0) @@ -244,165 +216,166 @@ namespace return S_OK; } +} - //------------------------------------------------------------------------------------- - // Encodes DDS file header (magic value, header, XBOX extended header) - //------------------------------------------------------------------------------------- - HRESULT EncodeDDSHeader( - const XboxImage& xbox, - _Out_writes_(maxsize) void* pDestination, - size_t maxsize) - { - if (!pDestination) - return E_POINTER; - - if (maxsize < XBOX_HEADER_SIZE) - return E_NOT_SUFFICIENT_BUFFER; +//===================================================================================== +// Entry-points +//===================================================================================== - *reinterpret_cast(pDestination) = DDS_MAGIC; +//------------------------------------------------------------------------------------- +// Encodes DDS file header (magic value, header, XBOX extended header) +//------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT Xbox::EncodeDDSHeader( + const XboxImage& xbox, + void* pDestination, + size_t maxsize) noexcept +{ + if (!pDestination) + return E_INVALIDARG; - auto header = reinterpret_cast(reinterpret_cast(pDestination) + sizeof(uint32_t)); + if (maxsize < DDS_XBOX_HEADER_SIZE) + return E_NOT_SUFFICIENT_BUFFER; - memset(header, 0, sizeof(DDS_HEADER)); - header->size = sizeof(DDS_HEADER); - header->flags = DDS_HEADER_FLAGS_TEXTURE; - header->caps = DDS_SURFACE_FLAGS_TEXTURE; + *reinterpret_cast(pDestination) = DDS_MAGIC; - auto& metadata = xbox.GetMetadata(); + auto header = reinterpret_cast(reinterpret_cast(pDestination) + sizeof(uint32_t)); - if (metadata.mipLevels > 0) - { - header->flags |= DDS_HEADER_FLAGS_MIPMAP; + memset(header, 0, sizeof(DDS_HEADER)); + header->size = sizeof(DDS_HEADER); + header->flags = DDS_HEADER_FLAGS_TEXTURE; + header->caps = DDS_SURFACE_FLAGS_TEXTURE; - if (metadata.mipLevels > UINT32_MAX) - return E_INVALIDARG; + auto& metadata = xbox.GetMetadata(); - header->mipMapCount = static_cast(metadata.mipLevels); + if (metadata.mipLevels > 0) + { + header->flags |= DDS_HEADER_FLAGS_MIPMAP; - if (header->mipMapCount > 1) - header->caps |= DDS_SURFACE_FLAGS_MIPMAP; - } + if (metadata.mipLevels > UINT32_MAX) + return E_INVALIDARG; - switch (metadata.dimension) - { - case TEX_DIMENSION_TEXTURE1D: - if (metadata.width > UINT32_MAX) - return E_INVALIDARG; + header->mipMapCount = static_cast(metadata.mipLevels); - header->width = static_cast(metadata.width); - header->height = header->depth = 1; - break; + if (header->mipMapCount > 1) + header->caps |= DDS_SURFACE_FLAGS_MIPMAP; + } - case TEX_DIMENSION_TEXTURE2D: - if (metadata.height > UINT32_MAX - || metadata.width > UINT32_MAX) - return E_INVALIDARG; + switch (metadata.dimension) + { + case TEX_DIMENSION_TEXTURE1D: + if (metadata.width > UINT32_MAX) + return E_INVALIDARG; - header->height = static_cast(metadata.height); - header->width = static_cast(metadata.width); - header->depth = 1; + header->width = static_cast(metadata.width); + header->height = header->depth = 1; + break; - if (metadata.IsCubemap()) - { - header->caps |= DDS_SURFACE_FLAGS_CUBEMAP; - header->caps2 |= DDS_CUBEMAP_ALLFACES; - } - break; + case TEX_DIMENSION_TEXTURE2D: + if (metadata.height > UINT32_MAX + || metadata.width > UINT32_MAX) + return E_INVALIDARG; - case TEX_DIMENSION_TEXTURE3D: - if (metadata.height > UINT32_MAX - || metadata.width > UINT32_MAX - || metadata.depth > UINT32_MAX) - return E_INVALIDARG; - - header->flags |= DDS_HEADER_FLAGS_VOLUME; - header->caps2 |= DDS_FLAGS_VOLUME; - header->height = static_cast(metadata.height); - header->width = static_cast(metadata.width); - header->depth = static_cast(metadata.depth); - break; + header->height = static_cast(metadata.height); + header->width = static_cast(metadata.width); + header->depth = 1; - default: - return E_FAIL; + if (metadata.IsCubemap()) + { + header->caps |= DDS_SURFACE_FLAGS_CUBEMAP; + header->caps2 |= DDS_CUBEMAP_ALLFACES; } + break; - size_t rowPitch, slicePitch; - ComputePitch(metadata.format, metadata.width, metadata.height, rowPitch, slicePitch, CP_FLAGS_NONE); + case TEX_DIMENSION_TEXTURE3D: + if (metadata.height > UINT32_MAX + || metadata.width > UINT32_MAX + || metadata.depth > UINT32_MAX) + return E_INVALIDARG; - if (slicePitch > UINT32_MAX - || rowPitch > UINT32_MAX) - return E_FAIL; + header->flags |= DDS_HEADER_FLAGS_VOLUME; + header->caps2 |= DDS_FLAGS_VOLUME; + header->height = static_cast(metadata.height); + header->width = static_cast(metadata.width); + header->depth = static_cast(metadata.depth); + break; - if (IsCompressed(metadata.format)) - { - header->flags |= DDS_HEADER_FLAGS_LINEARSIZE; - header->pitchOrLinearSize = static_cast(slicePitch); - } - else - { - header->flags |= DDS_HEADER_FLAGS_PITCH; - header->pitchOrLinearSize = static_cast(rowPitch); - } + default: + return E_FAIL; + } - memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_XBOX, sizeof(DDS_PIXELFORMAT)); + size_t rowPitch, slicePitch; + ComputePitch(metadata.format, metadata.width, metadata.height, rowPitch, slicePitch, CP_FLAGS_NONE); - // Setup XBOX extended header - auto xboxext = reinterpret_cast(reinterpret_cast(header) + sizeof(DDS_HEADER)); + if (slicePitch > UINT32_MAX + || rowPitch > UINT32_MAX) + return E_FAIL; - memset(xboxext, 0, sizeof(DDS_HEADER_XBOX)); - xboxext->dxgiFormat = metadata.format; - xboxext->resourceDimension = metadata.dimension; + if (IsCompressed(metadata.format)) + { + header->flags |= DDS_HEADER_FLAGS_LINEARSIZE; + header->pitchOrLinearSize = static_cast(slicePitch); + } + else + { + header->flags |= DDS_HEADER_FLAGS_PITCH; + header->pitchOrLinearSize = static_cast(rowPitch); + } - if (metadata.arraySize > UINT32_MAX) - return E_INVALIDARG; + memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_XBOX, sizeof(DDS_PIXELFORMAT)); - static_assert(static_cast(TEX_MISC_TEXTURECUBE) == static_cast(DDS_RESOURCE_MISC_TEXTURECUBE), "DDS header mismatch"); - xboxext->miscFlag = metadata.miscFlags & ~static_cast(TEX_MISC_TEXTURECUBE); + // Setup XBOX extended header + auto xboxext = reinterpret_cast(reinterpret_cast(header) + sizeof(DDS_HEADER)); - if (metadata.miscFlags & TEX_MISC_TEXTURECUBE) - { - xboxext->miscFlag |= TEX_MISC_TEXTURECUBE; - assert((metadata.arraySize % 6) == 0); - xboxext->arraySize = static_cast(metadata.arraySize / 6); - } - else - { - xboxext->arraySize = static_cast(metadata.arraySize); - } + memset(xboxext, 0, sizeof(DDS_HEADER_XBOX)); + xboxext->dxgiFormat = metadata.format; + xboxext->resourceDimension = metadata.dimension; - static_assert(static_cast(TEX_MISC2_ALPHA_MODE_MASK) == static_cast(DDS_MISC_FLAGS2_ALPHA_MODE_MASK), "DDS header mismatch"); + if (metadata.arraySize > UINT32_MAX) + return E_INVALIDARG; - static_assert(static_cast(TEX_ALPHA_MODE_UNKNOWN) == static_cast(DDS_ALPHA_MODE_UNKNOWN), "DDS header mismatch"); - static_assert(static_cast(TEX_ALPHA_MODE_STRAIGHT) == static_cast(DDS_ALPHA_MODE_STRAIGHT), "DDS header mismatch"); - static_assert(static_cast(TEX_ALPHA_MODE_PREMULTIPLIED) == static_cast(DDS_ALPHA_MODE_PREMULTIPLIED), "DDS header mismatch"); - static_assert(static_cast(TEX_ALPHA_MODE_OPAQUE) == static_cast(DDS_ALPHA_MODE_OPAQUE), "DDS header mismatch"); - static_assert(static_cast(TEX_ALPHA_MODE_CUSTOM) == static_cast(DDS_ALPHA_MODE_CUSTOM), "DDS header mismatch"); + static_assert(static_cast(TEX_MISC_TEXTURECUBE) == static_cast(DDS_RESOURCE_MISC_TEXTURECUBE), "DDS header mismatch"); + xboxext->miscFlag = metadata.miscFlags & ~static_cast(TEX_MISC_TEXTURECUBE); - xboxext->miscFlags2 = metadata.miscFlags2; + if (metadata.miscFlags & TEX_MISC_TEXTURECUBE) + { + xboxext->miscFlag |= TEX_MISC_TEXTURECUBE; + assert((metadata.arraySize % 6) == 0); + xboxext->arraySize = static_cast(metadata.arraySize / 6); + } + else + { + xboxext->arraySize = static_cast(metadata.arraySize); + } - #if defined(_GAMING_XBOX_SCARLETT) || defined(_USE_SCARLETT) - xboxext->tileMode = static_cast(xbox.GetTileMode()) | XBOX_TILEMODE_SCARLETT; - #else - xboxext->tileMode = static_cast(xbox.GetTileMode()); - #endif + static_assert(static_cast(TEX_MISC2_ALPHA_MODE_MASK) == static_cast(DDS_MISC_FLAGS2_ALPHA_MODE_MASK), "DDS header mismatch"); - xboxext->baseAlignment = xbox.GetAlignment(); - xboxext->dataSize = xbox.GetSize(); - #ifdef _GXDK_VER - xboxext->xdkVer = _GXDK_VER; - #elif defined(_XDK_VER) - xboxext->xdkVer = _XDK_VER; - #endif + static_assert(static_cast(TEX_ALPHA_MODE_UNKNOWN) == static_cast(DDS_ALPHA_MODE_UNKNOWN), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_STRAIGHT) == static_cast(DDS_ALPHA_MODE_STRAIGHT), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_PREMULTIPLIED) == static_cast(DDS_ALPHA_MODE_PREMULTIPLIED), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_OPAQUE) == static_cast(DDS_ALPHA_MODE_OPAQUE), "DDS header mismatch"); + static_assert(static_cast(TEX_ALPHA_MODE_CUSTOM) == static_cast(DDS_ALPHA_MODE_CUSTOM), "DDS header mismatch"); - return S_OK; - } -} + xboxext->miscFlags2 = metadata.miscFlags2; +#if defined(_GAMING_XBOX_SCARLETT) || defined(_USE_SCARLETT) + xboxext->tileMode = static_cast(xbox.GetTileMode()) | XBOX_TILEMODE_SCARLETT; +#else + xboxext->tileMode = static_cast(xbox.GetTileMode()); +#endif + + xboxext->baseAlignment = xbox.GetAlignment(); + xboxext->dataSize = xbox.GetSize(); +#ifdef _GXDK_VER + xboxext->xdkVer = _GXDK_VER; +#elif defined(_XDK_VER) + xboxext->xdkVer = _XDK_VER; +#endif + + return S_OK; +} -//===================================================================================== -// Entry-points -//===================================================================================== //------------------------------------------------------------------------------------- // Obtain metadata from DDS file in memory/on disk @@ -491,16 +464,16 @@ HRESULT Xbox::GetMetadataFromDDSFileEx( } // Need at least enough data to fill the standard header and magic number to be a valid DDS - if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + if (fileInfo.EndOfFile.LowPart < DDS_MIN_HEADER_SIZE) { return E_FAIL; } // Read the header in (including extended header if present) - uint8_t header[XBOX_HEADER_SIZE] = {}; + uint8_t header[DDS_XBOX_HEADER_SIZE] = {}; DWORD bytesRead = 0; - if (!ReadFile(hFile.get(), header, XBOX_HEADER_SIZE, &bytesRead, nullptr)) + if (!ReadFile(hFile.get(), header, DDS_XBOX_HEADER_SIZE, &bytesRead, nullptr)) { return HRESULT_FROM_WIN32(GetLastError()); } @@ -566,13 +539,13 @@ HRESULT Xbox::LoadFromDDSMemoryEx( return E_FAIL; } - if (size <= XBOX_HEADER_SIZE) + if (size <= DDS_XBOX_HEADER_SIZE) { return E_FAIL; } // Copy tiled data - const size_t remaining = size - XBOX_HEADER_SIZE; + const size_t remaining = size - DDS_XBOX_HEADER_SIZE; if (remaining < dataSize) { @@ -585,7 +558,7 @@ HRESULT Xbox::LoadFromDDSMemoryEx( assert(xbox.GetPointer() != nullptr); - memcpy(xbox.GetPointer(), reinterpret_cast(pSource) + XBOX_HEADER_SIZE, dataSize); + memcpy(xbox.GetPointer(), reinterpret_cast(pSource) + DDS_XBOX_HEADER_SIZE, dataSize); if (metadata) memcpy(metadata, &mdata, sizeof(TexMetadata)); @@ -644,16 +617,16 @@ HRESULT Xbox::LoadFromDDSFileEx( } // Need at least enough data to fill the standard header and magic number to be a valid DDS - if (fileInfo.EndOfFile.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + if (fileInfo.EndOfFile.LowPart < DDS_MIN_HEADER_SIZE) { return E_FAIL; } // Read the header in (including extended header if present) - uint8_t header[XBOX_HEADER_SIZE] = {}; + uint8_t header[DDS_XBOX_HEADER_SIZE] = {}; DWORD bytesRead = 0; - if (!ReadFile(hFile.get(), header, XBOX_HEADER_SIZE, &bytesRead, nullptr)) + if (!ReadFile(hFile.get(), header, DDS_XBOX_HEADER_SIZE, &bytesRead, nullptr)) { return HRESULT_FROM_WIN32(GetLastError()); } @@ -677,7 +650,7 @@ HRESULT Xbox::LoadFromDDSFileEx( } // Read tiled data - const DWORD remaining = fileInfo.EndOfFile.LowPart - XBOX_HEADER_SIZE; + const DWORD remaining = fileInfo.EndOfFile.LowPart - DDS_XBOX_HEADER_SIZE; if (remaining == 0) return E_FAIL; @@ -716,7 +689,7 @@ HRESULT Xbox::SaveToDDSMemory(const XboxImage& xbox, Blob& blob) blob.Release(); - HRESULT hr = blob.Initialize(XBOX_HEADER_SIZE + xbox.GetSize()); + HRESULT hr = blob.Initialize(DDS_XBOX_HEADER_SIZE + xbox.GetSize()); if (FAILED(hr)) return hr; @@ -724,7 +697,7 @@ HRESULT Xbox::SaveToDDSMemory(const XboxImage& xbox, Blob& blob) auto pDestination = reinterpret_cast(blob.GetBufferPointer()); assert(pDestination); - hr = EncodeDDSHeader(xbox, pDestination, XBOX_HEADER_SIZE); + hr = EncodeDDSHeader(xbox, pDestination, DDS_XBOX_HEADER_SIZE); if (FAILED(hr)) { blob.Release(); @@ -732,8 +705,8 @@ HRESULT Xbox::SaveToDDSMemory(const XboxImage& xbox, Blob& blob) } // Copy tiled data - const size_t remaining = blob.GetBufferSize() - XBOX_HEADER_SIZE; - pDestination += XBOX_HEADER_SIZE; + const size_t remaining = blob.GetBufferSize() - DDS_XBOX_HEADER_SIZE; + pDestination += DDS_XBOX_HEADER_SIZE; if (!remaining) { @@ -763,8 +736,8 @@ HRESULT Xbox::SaveToDDSFile(const XboxImage& xbox, const wchar_t* szFile) return E_INVALIDARG; // Create DDS Header - uint8_t header[XBOX_HEADER_SIZE] = {}; - HRESULT hr = EncodeDDSHeader(xbox, header, XBOX_HEADER_SIZE); + uint8_t header[DDS_XBOX_HEADER_SIZE] = {}; + HRESULT hr = EncodeDDSHeader(xbox, header, DDS_XBOX_HEADER_SIZE); if (FAILED(hr)) return hr; @@ -782,12 +755,12 @@ HRESULT Xbox::SaveToDDSFile(const XboxImage& xbox, const wchar_t* szFile) } DWORD bytesWritten; - if (!WriteFile(hFile.get(), header, static_cast(XBOX_HEADER_SIZE), &bytesWritten, nullptr)) + if (!WriteFile(hFile.get(), header, static_cast(DDS_XBOX_HEADER_SIZE), &bytesWritten, nullptr)) { return HRESULT_FROM_WIN32(GetLastError()); } - if (bytesWritten != XBOX_HEADER_SIZE) + if (bytesWritten != DDS_XBOX_HEADER_SIZE) { return E_FAIL; } diff --git a/CMakeLists.txt b/CMakeLists.txt index 7dc069a8..7f240c67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -591,7 +591,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") endforeach() endif() - set(WarningsEXE "/wd4061" "/wd4062" "/wd4365" "/wd4514" "/wd4625" "/wd4626" "/wd4627" "/wd4668" "/wd4710" "/wd4711" "/wd4751" "/wd4820" "/wd5026" "/wd5027" "/wd5039" "/wd5045" "/wd5219") + set(WarningsEXE "/wd4061" "/wd4062" "/wd4365" "/wd4514" "/wd4571" "/wd4625" "/wd4626" "/wd4627" "/wd4668" "/wd4710" "/wd4711" "/wd4751" "/wd4774" "/wd4820" "/wd5026" "/wd5027" "/wd5039" "/wd5045" "/wd5219") if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.34) list(APPEND WarningsEXE "/wd5262" "/wd5264") endif() diff --git a/DirectXTex/DDS.h b/DirectXTex/DDS.h index cce220c7..9fcaad64 100644 --- a/DirectXTex/DDS.h +++ b/DirectXTex/DDS.h @@ -39,17 +39,18 @@ namespace DirectX uint32_t ABitMask; }; -#define DDS_FOURCC 0x00000004 // DDPF_FOURCC -#define DDS_RGB 0x00000040 // DDPF_RGB -#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS -#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE -#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS -#define DDS_ALPHAPIXELS 0x00000001 // DDPF_ALPHAPIXELS -#define DDS_ALPHA 0x00000002 // DDPF_ALPHA -#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8 -#define DDS_PAL8A 0x00000021 // DDPF_PALETTEINDEXED8 | DDPF_ALPHAPIXELS -#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV -// DDS_BUMPLUMINANCE 0x00040000 +#define DDS_FOURCC 0x00000004 // DDPF_FOURCC +#define DDS_RGB 0x00000040 // DDPF_RGB +#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS +#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE +#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS +#define DDS_ALPHAPIXELS 0x00000001 // DDPF_ALPHAPIXELS +#define DDS_ALPHA 0x00000002 // DDPF_ALPHA +#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8 +#define DDS_PAL8A 0x00000021 // DDPF_PALETTEINDEXED8 | DDPF_ALPHAPIXELS +#define DDS_BUMPLUMINANCE 0x00040000 // DDPF_BUMPLUMINANCE +#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV +#define DDS_BUMPDUDVA 0x00080001 // DDPF_BUMPDUDV | DDPF_ALPHAPIXELS #ifndef MAKEFOURCC #define MAKEFOURCC(ch0, ch1, ch2, ch3) \ @@ -187,10 +188,13 @@ namespace DirectX DDSGLOBALCONST DDS_PIXELFORMAT DDSPF_A2B10G10R10 = { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }; -// We do not support the following legacy Direct3D 9 formats: -// DDSPF_A2W10V10U10 = { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }; -// DDSPF_L6V5U5 = { sizeof(DDS_PIXELFORMAT), DDS_BUMPLUMINANCE, 0, 16, 0x001f, 0x03e0, 0xfc00, 0 }; -// DDSPF_X8L8V8U8 = { sizeof(DDS_PIXELFORMAT), DDS_BUMPLUMINANCE, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0 }; +// The following legacy Direct3D 9 formats use 'mixed' signed & unsigned channels so requires special handling + DDSGLOBALCONST DDS_PIXELFORMAT DDSPF_A2W10V10U10 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDVA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }; + DDSGLOBALCONST DDS_PIXELFORMAT DDSPF_L6V5U5 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPLUMINANCE, 0, 16, 0x001f, 0x03e0, 0xfc00, 0 }; + DDSGLOBALCONST DDS_PIXELFORMAT DDSPF_X8L8V8U8 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPLUMINANCE, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0 }; // This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat) DDSGLOBALCONST DDS_PIXELFORMAT DDSPF_DX10 = @@ -288,4 +292,39 @@ namespace DirectX static_assert(sizeof(DDS_HEADER) == 124, "DDS Header size mismatch"); static_assert(sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch"); + constexpr size_t DDS_MIN_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER); + constexpr size_t DDS_DX10_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10); + static_assert(DDS_DX10_HEADER_SIZE > DDS_MIN_HEADER_SIZE, "DDS DX10 Header should be larger than standard header"); + +} // namespace + +namespace Xbox +{ + DDSGLOBALCONST DirectX::DDS_PIXELFORMAT DDSPF_XBOX = + { sizeof(DirectX::DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('X','B','O','X'), 0, 0, 0, 0, 0 }; + +#pragma pack(push,1) + + struct DDS_HEADER_XBOX + // Must match structure in XboxDDSTextureLoader module + { + DXGI_FORMAT dxgiFormat; + uint32_t resourceDimension; + uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG + uint32_t arraySize; + uint32_t miscFlags2; // see DDS_MISC_FLAGS2 + uint32_t tileMode; // see XG_TILE_MODE / XG_SWIZZLE_MODE + uint32_t baseAlignment; + uint32_t dataSize; + uint32_t xdkVer; // matching _XDK_VER / _GXDK_VER + }; + +#pragma pack(pop) + + static_assert(sizeof(DDS_HEADER_XBOX) == 36, "DDS XBOX Header size mismatch"); + static_assert(sizeof(DDS_HEADER_XBOX) > sizeof(DirectX::DDS_HEADER_DXT10), "DDS XBOX Header should be larger than DX10 header"); + + constexpr size_t DDS_XBOX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DirectX::DDS_HEADER) + sizeof(DDS_HEADER_XBOX); + + constexpr uint32_t XBOX_TILEMODE_SCARLETT = 0x1000000; } // namespace diff --git a/DirectXTex/DirectXTexDDS.cpp b/DirectXTex/DirectXTexDDS.cpp index 585587e4..0daf9423 100644 --- a/DirectXTex/DirectXTexDDS.cpp +++ b/DirectXTex/DirectXTexDDS.cpp @@ -22,8 +22,6 @@ static_assert(static_cast(TEX_DIMENSION_TEXTURE3D) == static_cast(DDS_ namespace { - constexpr size_t MAX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10); - //------------------------------------------------------------------------------------- // Legacy format mapping table (used for DDS files without 'DX10' extended header) //------------------------------------------------------------------------------------- @@ -326,7 +324,7 @@ namespace *ddPixelFormat = {}; } - if (size < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + if (size < DDS_MIN_HEADER_SIZE) { return HRESULT_E_INVALID_DATA; } @@ -386,12 +384,12 @@ namespace } // Buffer must be big enough for both headers and magic value - if (size < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10))) + if (size < DDS_DX10_HEADER_SIZE) { return E_FAIL; } - auto d3d10ext = reinterpret_cast(static_cast(pSource) + sizeof(uint32_t) + sizeof(DDS_HEADER)); + auto d3d10ext = reinterpret_cast(static_cast(pSource) + DDS_MIN_HEADER_SIZE); convFlags |= CONV_FLAGS_DX10; metadata.arraySize = d3d10ext->arraySize; @@ -826,7 +824,7 @@ HRESULT DirectX::EncodeDDSHeader( } } - required = sizeof(uint32_t) + sizeof(DDS_HEADER); + required = DDS_MIN_HEADER_SIZE; if (ddpf.size == 0) { @@ -1776,24 +1774,24 @@ HRESULT DirectX::GetMetadataFromDDSFileEx( #endif // Need at least enough data to fill the standard header and magic number to be a valid DDS - if (len < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + if (len < DDS_MIN_HEADER_SIZE) { return E_FAIL; } // Read the header in (including extended header if present) - uint8_t header[MAX_HEADER_SIZE] = {}; + uint8_t header[DDS_DX10_HEADER_SIZE] = {}; #ifdef _WIN32 DWORD bytesRead = 0; - if (!ReadFile(hFile.get(), header, MAX_HEADER_SIZE, &bytesRead, nullptr)) + if (!ReadFile(hFile.get(), header, DDS_DX10_HEADER_SIZE, &bytesRead, nullptr)) { return HRESULT_FROM_WIN32(GetLastError()); } auto const headerLen = static_cast(bytesRead); #else - auto const headerLen = std::min(len, MAX_HEADER_SIZE); + auto const headerLen = std::min(len, DDS_DX10_HEADER_SIZE); inFile.read(reinterpret_cast(header), headerLen); if (!inFile) @@ -1839,7 +1837,7 @@ HRESULT DirectX::LoadFromDDSMemoryEx( if (FAILED(hr)) return hr; - size_t offset = sizeof(uint32_t) + sizeof(DDS_HEADER); + size_t offset = DDS_MIN_HEADER_SIZE; if (convFlags & CONV_FLAGS_DX10) offset += sizeof(DDS_HEADER_DXT10); @@ -1960,24 +1958,24 @@ HRESULT DirectX::LoadFromDDSFileEx( #endif // Need at least enough data to fill the standard header and magic number to be a valid DDS - if (len < (sizeof(DDS_HEADER) + sizeof(uint32_t))) + if (len < DDS_MIN_HEADER_SIZE) { return E_FAIL; } // Read the header in (including extended header if present) - uint8_t header[MAX_HEADER_SIZE] = {}; + uint8_t header[DDS_DX10_HEADER_SIZE] = {}; #ifdef _WIN32 DWORD bytesRead = 0; - if (!ReadFile(hFile.get(), header, MAX_HEADER_SIZE, &bytesRead, nullptr)) + if (!ReadFile(hFile.get(), header, DDS_DX10_HEADER_SIZE, &bytesRead, nullptr)) { return HRESULT_FROM_WIN32(GetLastError()); } auto const headerLen = static_cast(bytesRead); #else - auto const headerLen = std::min(len, MAX_HEADER_SIZE); + auto const headerLen = std::min(len, DDS_DX10_HEADER_SIZE); inFile.read(reinterpret_cast(header), headerLen); if (!inFile) @@ -1990,24 +1988,24 @@ HRESULT DirectX::LoadFromDDSFileEx( if (FAILED(hr)) return hr; - size_t offset = MAX_HEADER_SIZE; + size_t offset = DDS_DX10_HEADER_SIZE; if (!(convFlags & CONV_FLAGS_DX10)) { #ifdef _WIN32 // Must reset file position since we read more than the standard header above - const LARGE_INTEGER filePos = { { sizeof(uint32_t) + sizeof(DDS_HEADER), 0 } }; + const LARGE_INTEGER filePos = { { DDS_MIN_HEADER_SIZE, 0 } }; if (!SetFilePointerEx(hFile.get(), filePos, nullptr, FILE_BEGIN)) { return HRESULT_FROM_WIN32(GetLastError()); } #else - inFile.seekg(sizeof(uint32_t) + sizeof(DDS_HEADER), std::ios::beg); + inFile.seekg(DDS_MIN_HEADER_SIZE, std::ios::beg); if (!inFile) return E_FAIL; #endif - offset = sizeof(uint32_t) + sizeof(DDS_HEADER); + offset = DDS_MIN_HEADER_SIZE; } std::unique_ptr pal8; @@ -2393,9 +2391,9 @@ HRESULT DirectX::SaveToDDSFile( return E_INVALIDARG; // Create DDS Header - uint8_t header[MAX_HEADER_SIZE]; + uint8_t header[DDS_DX10_HEADER_SIZE]; size_t required; - HRESULT hr = EncodeDDSHeader(metadata, flags, header, MAX_HEADER_SIZE, required); + HRESULT hr = EncodeDDSHeader(metadata, flags, header, DDS_DX10_HEADER_SIZE, required); if (FAILED(hr)) return hr; diff --git a/Texconv/PortablePixMap.cpp b/Texconv/PortablePixMap.cpp index 9501c43b..a360c48c 100644 --- a/Texconv/PortablePixMap.cpp +++ b/Texconv/PortablePixMap.cpp @@ -14,7 +14,7 @@ #pragma warning(disable : 4005) #endif #define WIN32_LEAN_AND_MEAN -#define NOMINMAX +#define NOMINMAX 1 #define NODRAWTEXT #define NOMCX #define NOSERVICE @@ -25,6 +25,7 @@ #include +#include #include #include #include diff --git a/build/CompilerAndLinker.cmake b/build/CompilerAndLinker.cmake index 197b1c34..8950d5ca 100644 --- a/build/CompilerAndLinker.cmake +++ b/build/CompilerAndLinker.cmake @@ -85,18 +85,40 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|IntelLLVM") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") list(APPEND COMPILER_SWITCHES /Zc:__cplusplus /Zc:inline /fp:fast /Qdiag-disable:161) elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - list(APPEND COMPILER_SWITCHES /sdl /permissive- /JMC- /Zc:__cplusplus /Zc:inline /fp:fast) + list(APPEND COMPILER_SWITCHES /sdl /Zc:inline /fp:fast) if(CMAKE_INTERPROCEDURAL_OPTIMIZATION) message(STATUS "Building using Whole Program Optimization") list(APPEND COMPILER_SWITCHES $<$>:/Gy /Gw>) endif() - if(OpenMP_CXX_FOUND) + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.10) + list(APPEND COMPILER_SWITCHES /permissive-) + endif() + + if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.11) + AND (OpenMP_CXX_FOUND + OR (XBOX_CONSOLE_TARGET STREQUAL "durango"))) # OpenMP in MSVC is not compatible with /permissive- unless you disable two-phase lookup list(APPEND COMPILER_SWITCHES /Zc:twoPhase-) endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.14) + list(APPEND COMPILER_SWITCHES /Zc:__cplusplus) + endif() + + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.15) + list(APPEND COMPILER_SWITCHES /JMC-) + endif() + + if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.20) + AND (XBOX_CONSOLE_TARGET STREQUAL "durango")) + list(APPEND COMPILER_SWITCHES /d2FH4-) + if(CMAKE_INTERPROCEDURAL_OPTIMIZATION) + list(APPEND LINKER_SWITCHES -d2:-FH4-) + endif() + endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.24) list(APPEND COMPILER_SWITCHES /ZH:SHA_256) endif() @@ -114,6 +136,10 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") list(APPEND COMPILER_SWITCHES /Zc:lambda) endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29) + list(APPEND COMPILER_SWITCHES /external:W4) + endif() + if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.31) AND (XBOX_CONSOLE_TARGET STREQUAL "durango")) list(APPEND COMPILER_SWITCHES /Zc:static_assert-)