From 09affb78aa873ae53bceeba9c3e4adf04c353942 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Mon, 14 Oct 2024 15:49:44 -0700 Subject: [PATCH] Fix DX12 Capture transition state handling for MSAA (#532) --- DDSTextureLoader/DDSTextureLoader11.cpp | 170 ++++++++++++----------- DDSTextureLoader/DDSTextureLoader12.cpp | 172 +++++++++++++----------- DDSTextureLoader/DDSTextureLoader9.cpp | 138 ++++++++++--------- DirectXTex/DirectXTexD3D12.cpp | 16 ++- ScreenGrab/ScreenGrab11.cpp | 46 ++++--- ScreenGrab/ScreenGrab12.cpp | 64 +++++---- ScreenGrab/ScreenGrab9.cpp | 48 ++++--- 7 files changed, 356 insertions(+), 298 deletions(-) diff --git a/DDSTextureLoader/DDSTextureLoader11.cpp b/DDSTextureLoader/DDSTextureLoader11.cpp index eed802b..6a60a46 100644 --- a/DDSTextureLoader/DDSTextureLoader11.cpp +++ b/DDSTextureLoader/DDSTextureLoader11.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -52,83 +53,91 @@ using namespace DirectX; // DDS file structure definitions // // See DDS.h in the 'Texconv' sample and the 'DirectXTex' library -//-------------------------------------------------------------------------------------- -#pragma pack(push,1) - -constexpr uint32_t DDS_MAGIC = 0x20534444; // "DDS " - -struct DDS_PIXELFORMAT -{ - uint32_t size; - uint32_t flags; - uint32_t fourCC; - uint32_t RGBBitCount; - uint32_t RBitMask; - uint32_t GBitMask; - uint32_t BBitMask; - uint32_t ABitMask; -}; - -#define DDS_FOURCC 0x00000004 // DDPF_FOURCC -#define DDS_RGB 0x00000040 // DDPF_RGB -#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE -#define DDS_ALPHA 0x00000002 // DDPF_ALPHA -#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV - -#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH - -#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT - -#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX -#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX -#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY -#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY -#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ -#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ - -#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ - DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ - DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ ) - -#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP - -enum DDS_MISC_FLAGS2 -{ - DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L, -}; - -struct DDS_HEADER -{ - uint32_t size; - uint32_t flags; - uint32_t height; - uint32_t width; - uint32_t pitchOrLinearSize; - uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags - uint32_t mipMapCount; - uint32_t reserved1[11]; - DDS_PIXELFORMAT ddspf; - uint32_t caps; - uint32_t caps2; - uint32_t caps3; - uint32_t caps4; - uint32_t reserved2; -}; - -struct DDS_HEADER_DXT10 -{ - DXGI_FORMAT dxgiFormat; - uint32_t resourceDimension; - uint32_t miscFlag; // see D3D11_RESOURCE_MISC_FLAG - uint32_t arraySize; - uint32_t miscFlags2; -}; - -#pragma pack(pop) - //-------------------------------------------------------------------------------------- namespace { + #pragma pack(push,1) + + constexpr uint32_t DDS_MAGIC = 0x20534444; // "DDS " + + struct DDS_PIXELFORMAT + { + uint32_t size; + uint32_t flags; + uint32_t fourCC; + uint32_t RGBBitCount; + uint32_t RBitMask; + uint32_t GBitMask; + uint32_t BBitMask; + uint32_t ABitMask; + }; + + #define DDS_FOURCC 0x00000004 // DDPF_FOURCC + #define DDS_RGB 0x00000040 // DDPF_RGB + #define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE + #define DDS_ALPHA 0x00000002 // DDPF_ALPHA + #define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV + + #define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH + + #define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT + + #define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX + #define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX + #define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY + #define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY + #define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ + #define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ + + #define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ + DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ + DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ ) + + #define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP + + enum DDS_MISC_FLAGS2 + { + DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L, + }; + + struct DDS_HEADER + { + uint32_t size; + uint32_t flags; + uint32_t height; + uint32_t width; + uint32_t pitchOrLinearSize; + uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags + uint32_t mipMapCount; + uint32_t reserved1[11]; + DDS_PIXELFORMAT ddspf; + uint32_t caps; + uint32_t caps2; + uint32_t caps3; + uint32_t caps4; + uint32_t reserved2; + }; + + struct DDS_HEADER_DXT10 + { + DXGI_FORMAT dxgiFormat; + uint32_t resourceDimension; + uint32_t miscFlag; // see D3D11_RESOURCE_MISC_FLAG + uint32_t arraySize; + uint32_t miscFlags2; + }; + + #pragma pack(pop) + + static_assert(sizeof(DDS_PIXELFORMAT) == 32, "DDS pixel format size mismatch"); + 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"); + + //-------------------------------------------------------------------------------------- struct handle_closer { void operator()(HANDLE h) noexcept { if (h) CloseHandle(h); } }; using ScopedHandle = std::unique_ptr; @@ -168,7 +177,7 @@ namespace return E_FAIL; } - if (ddsDataSize < (sizeof(uint32_t) + sizeof(DDS_HEADER))) + if (ddsDataSize < DDS_MIN_HEADER_SIZE) { return E_FAIL; } @@ -195,7 +204,7 @@ namespace (MAKEFOURCC('D', 'X', '1', '0') == hdr->ddspf.fourCC)) { // Must be long enough for both headers and magic value - if (ddsDataSize < (sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10))) + if (ddsDataSize < DDS_DX10_HEADER_SIZE) { return E_FAIL; } @@ -205,8 +214,7 @@ namespace // setup the pointers in the process request *header = hdr; - auto offset = sizeof(uint32_t) - + sizeof(DDS_HEADER) + auto offset = DDS_MIN_HEADER_SIZE + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0u); *bitData = ddsData + offset; *bitSize = ddsDataSize - offset; @@ -264,7 +272,7 @@ namespace } // Need at least enough data to fill the header and magic number to be a valid DDS - if (fileInfo.EndOfFile.LowPart < (sizeof(uint32_t) + sizeof(DDS_HEADER))) + if (fileInfo.EndOfFile.LowPart < DDS_MIN_HEADER_SIZE) { return E_FAIL; } @@ -319,7 +327,7 @@ namespace (MAKEFOURCC('D', 'X', '1', '0') == hdr->ddspf.fourCC)) { // Must be long enough for both headers and magic value - if (fileInfo.EndOfFile.LowPart < (sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10))) + if (fileInfo.EndOfFile.LowPart < DDS_DX10_HEADER_SIZE) { ddsData.reset(); return E_FAIL; @@ -330,7 +338,7 @@ namespace // setup the pointers in the process request *header = hdr; - auto offset = sizeof(uint32_t) + sizeof(DDS_HEADER) + auto offset = DDS_MIN_HEADER_SIZE + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0u); *bitData = ddsData.get() + offset; *bitSize = fileInfo.EndOfFile.LowPart - offset; diff --git a/DDSTextureLoader/DDSTextureLoader12.cpp b/DDSTextureLoader/DDSTextureLoader12.cpp index df909a4..b1407c5 100644 --- a/DDSTextureLoader/DDSTextureLoader12.cpp +++ b/DDSTextureLoader/DDSTextureLoader12.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -80,83 +81,91 @@ using namespace DirectX; // DDS file structure definitions // // See DDS.h in the 'Texconv' sample and the 'DirectXTex' library -//-------------------------------------------------------------------------------------- -#pragma pack(push,1) - -constexpr uint32_t DDS_MAGIC = 0x20534444; // "DDS " - -struct DDS_PIXELFORMAT -{ - uint32_t size; - uint32_t flags; - uint32_t fourCC; - uint32_t RGBBitCount; - uint32_t RBitMask; - uint32_t GBitMask; - uint32_t BBitMask; - uint32_t ABitMask; -}; - -#define DDS_FOURCC 0x00000004 // DDPF_FOURCC -#define DDS_RGB 0x00000040 // DDPF_RGB -#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE -#define DDS_ALPHA 0x00000002 // DDPF_ALPHA -#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV - -#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH - -#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT - -#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX -#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX -#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY -#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY -#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ -#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ - -#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ - DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ - DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ ) - -#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP - -enum DDS_MISC_FLAGS2 -{ - DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L, -}; - -struct DDS_HEADER -{ - uint32_t size; - uint32_t flags; - uint32_t height; - uint32_t width; - uint32_t pitchOrLinearSize; - uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags - uint32_t mipMapCount; - uint32_t reserved1[11]; - DDS_PIXELFORMAT ddspf; - uint32_t caps; - uint32_t caps2; - uint32_t caps3; - uint32_t caps4; - uint32_t reserved2; -}; - -struct DDS_HEADER_DXT10 -{ - DXGI_FORMAT dxgiFormat; - uint32_t resourceDimension; - uint32_t miscFlag; // see D3D11_RESOURCE_MISC_FLAG - uint32_t arraySize; - uint32_t miscFlags2; -}; - -#pragma pack(pop) - //-------------------------------------------------------------------------------------- namespace { + #pragma pack(push,1) + + constexpr uint32_t DDS_MAGIC = 0x20534444; // "DDS " + + struct DDS_PIXELFORMAT + { + uint32_t size; + uint32_t flags; + uint32_t fourCC; + uint32_t RGBBitCount; + uint32_t RBitMask; + uint32_t GBitMask; + uint32_t BBitMask; + uint32_t ABitMask; + }; + + #define DDS_FOURCC 0x00000004 // DDPF_FOURCC + #define DDS_RGB 0x00000040 // DDPF_RGB + #define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE + #define DDS_ALPHA 0x00000002 // DDPF_ALPHA + #define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV + + #define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH + + #define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT + + #define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX + #define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX + #define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY + #define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY + #define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ + #define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ + + #define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ + DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ + DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ ) + + #define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP + + enum DDS_MISC_FLAGS2 + { + DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L, + }; + + struct DDS_HEADER + { + uint32_t size; + uint32_t flags; + uint32_t height; + uint32_t width; + uint32_t pitchOrLinearSize; + uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags + uint32_t mipMapCount; + uint32_t reserved1[11]; + DDS_PIXELFORMAT ddspf; + uint32_t caps; + uint32_t caps2; + uint32_t caps3; + uint32_t caps4; + uint32_t reserved2; + }; + + struct DDS_HEADER_DXT10 + { + DXGI_FORMAT dxgiFormat; + uint32_t resourceDimension; + uint32_t miscFlag; // see D3D11_RESOURCE_MISC_FLAG + uint32_t arraySize; + uint32_t miscFlags2; + }; + + #pragma pack(pop) + + static_assert(sizeof(DDS_PIXELFORMAT) == 32, "DDS pixel format size mismatch"); + 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"); + + //-------------------------------------------------------------------------------------- #ifdef _WIN32 struct handle_closer { void operator()(HANDLE h) noexcept { if (h) CloseHandle(h); } }; @@ -214,7 +223,7 @@ namespace return E_FAIL; } - if (ddsDataSize < (sizeof(uint32_t) + sizeof(DDS_HEADER))) + if (ddsDataSize < DDS_MIN_HEADER_SIZE) { return E_FAIL; } @@ -241,7 +250,7 @@ namespace (MAKEFOURCC('D', 'X', '1', '0') == hdr->ddspf.fourCC)) { // Must be long enough for both headers and magic value - if (ddsDataSize < (sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10))) + if (ddsDataSize < DDS_DX10_HEADER_SIZE) { return E_FAIL; } @@ -251,8 +260,7 @@ namespace // setup the pointers in the process request *header = hdr; - auto offset = sizeof(uint32_t) - + sizeof(DDS_HEADER) + auto offset = DDS_MIN_HEADER_SIZE + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0u); *bitData = ddsData + offset; *bitSize = ddsDataSize - offset; @@ -302,7 +310,7 @@ namespace } // Need at least enough data to fill the header and magic number to be a valid DDS - if (fileInfo.EndOfFile.LowPart < (sizeof(uint32_t) + sizeof(DDS_HEADER))) + if (fileInfo.EndOfFile.LowPart < DDS_MIN_HEADER_SIZE) { return E_FAIL; } @@ -345,7 +353,7 @@ namespace return E_FAIL; // Need at least enough data to fill the header and magic number to be a valid DDS - if (fileLen < (sizeof(uint32_t) + sizeof(DDS_HEADER))) + if (fileLen < DDS_MIN_HEADER_SIZE) return E_FAIL; ddsData.reset(new (std::nothrow) uint8_t[size_t(fileLen)]); @@ -395,7 +403,7 @@ namespace (MAKEFOURCC('D', 'X', '1', '0') == hdr->ddspf.fourCC)) { // Must be long enough for both headers and magic value - if (len < (sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10))) + if (len < DDS_DX10_HEADER_SIZE) { ddsData.reset(); return E_FAIL; @@ -406,7 +414,7 @@ namespace // setup the pointers in the process request *header = hdr; - auto offset = sizeof(uint32_t) + sizeof(DDS_HEADER) + auto offset = DDS_MIN_HEADER_SIZE + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0u); *bitData = ddsData.get() + offset; *bitSize = len - offset; diff --git a/DDSTextureLoader/DDSTextureLoader9.cpp b/DDSTextureLoader/DDSTextureLoader9.cpp index eec7da0..329bddc 100644 --- a/DDSTextureLoader/DDSTextureLoader9.cpp +++ b/DDSTextureLoader/DDSTextureLoader9.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -56,68 +57,73 @@ using Microsoft::WRL::ComPtr; // DDS file structure definitions // // See DDS.h in the 'Texconv' sample and the 'DirectXTex' library -//-------------------------------------------------------------------------------------- -#pragma pack(push,1) - -constexpr uint32_t DDS_MAGIC = 0x20534444; // "DDS " - -struct DDS_PIXELFORMAT -{ - uint32_t size; - uint32_t flags; - uint32_t fourCC; - uint32_t RGBBitCount; - uint32_t RBitMask; - uint32_t GBitMask; - uint32_t BBitMask; - uint32_t ABitMask; -}; - -#define DDS_FOURCC 0x00000004 // DDPF_FOURCC -#define DDS_RGB 0x00000040 // DDPF_RGB -#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE -#define DDS_ALPHA 0x00000002 // DDPF_ALPHA -#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV -#define DDS_BUMPLUMINANCE 0x00040000 // DDPF_BUMPLUMINANCE - -#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH - -#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX -#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX -#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY -#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY -#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ -#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ - -#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ - DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ - DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ ) - -#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP - -struct DDS_HEADER -{ - uint32_t size; - uint32_t flags; - uint32_t height; - uint32_t width; - uint32_t pitchOrLinearSize; - uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags - uint32_t mipMapCount; - uint32_t reserved1[11]; - DDS_PIXELFORMAT ddspf; - uint32_t caps; - uint32_t caps2; - uint32_t caps3; - uint32_t caps4; - uint32_t reserved2; -}; - -#pragma pack(pop) - //-------------------------------------------------------------------------------------- namespace { + #pragma pack(push,1) + + constexpr uint32_t DDS_MAGIC = 0x20534444; // "DDS " + + struct DDS_PIXELFORMAT + { + uint32_t size; + uint32_t flags; + uint32_t fourCC; + uint32_t RGBBitCount; + uint32_t RBitMask; + uint32_t GBitMask; + uint32_t BBitMask; + uint32_t ABitMask; + }; + + #define DDS_FOURCC 0x00000004 // DDPF_FOURCC + #define DDS_RGB 0x00000040 // DDPF_RGB + #define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE + #define DDS_ALPHA 0x00000002 // DDPF_ALPHA + #define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV + #define DDS_BUMPLUMINANCE 0x00040000 // DDPF_BUMPLUMINANCE + + #define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH + + #define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX + #define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX + #define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY + #define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY + #define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ + #define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ + + #define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ + DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ + DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ ) + + #define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP + + struct DDS_HEADER + { + uint32_t size; + uint32_t flags; + uint32_t height; + uint32_t width; + uint32_t pitchOrLinearSize; + uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags + uint32_t mipMapCount; + uint32_t reserved1[11]; + DDS_PIXELFORMAT ddspf; + uint32_t caps; + uint32_t caps2; + uint32_t caps3; + uint32_t caps4; + uint32_t reserved2; + }; + + #pragma pack(pop) + + static_assert(sizeof(DDS_PIXELFORMAT) == 32, "DDS pixel format size mismatch"); + static_assert(sizeof(DDS_HEADER) == 124, "DDS Header size mismatch"); + + constexpr size_t DDS_DX9_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER); + + //-------------------------------------------------------------------------------------- struct handle_closer { void operator()(HANDLE h) noexcept { if (h) CloseHandle(h); } }; using ScopedHandle = std::unique_ptr; @@ -144,7 +150,7 @@ namespace return E_FAIL; } - if (ddsDataSize < (sizeof(uint32_t) + sizeof(DDS_HEADER))) + if (ddsDataSize < DDS_DX9_HEADER_SIZE) { return E_FAIL; } @@ -175,9 +181,8 @@ namespace // setup the pointers in the process request *header = hdr; - auto offset = sizeof(uint32_t) + sizeof(DDS_HEADER); - *bitData = ddsData + offset; - *bitSize = ddsDataSize - offset; + *bitData = ddsData + DDS_DX9_HEADER_SIZE; + *bitSize = ddsDataSize - DDS_DX9_HEADER_SIZE; return S_OK; } @@ -234,7 +239,7 @@ namespace } // Need at least enough data to fill the header and magic number to be a valid DDS - if (fileInfo.EndOfFile.LowPart < (sizeof(uint32_t) + sizeof(DDS_HEADER))) + if (fileInfo.EndOfFile.LowPart < DDS_DX9_HEADER_SIZE) { return E_FAIL; } @@ -294,9 +299,8 @@ namespace // setup the pointers in the process request *header = hdr; - auto offset = sizeof(uint32_t) + sizeof(DDS_HEADER); - *bitData = ddsData.get() + offset; - *bitSize = fileInfo.EndOfFile.LowPart - offset; + *bitData = ddsData.get() + DDS_DX9_HEADER_SIZE; + *bitSize = fileInfo.EndOfFile.LowPart - DDS_DX9_HEADER_SIZE; return S_OK; } diff --git a/DirectXTex/DirectXTexD3D12.cpp b/DirectXTex/DirectXTexD3D12.cpp index f6e48d6..eba8281 100644 --- a/DirectXTex/DirectXTexD3D12.cpp +++ b/DirectXTex/DirectXTexD3D12.cpp @@ -217,8 +217,11 @@ namespace bufferDesc.SampleDesc.Count = 1; ComPtr copySource(pSource); + D3D12_RESOURCE_STATES beforeStateSource = beforeState; if (desc.SampleDesc.Count > 1) { + TransitionResource(commandList.Get(), pSource, beforeState, D3D12_RESOURCE_STATE_RESOLVE_SOURCE); + // MSAA content must be resolved before being copied to a staging texture auto descCopy = desc; descCopy.SampleDesc.Count = 1; @@ -230,7 +233,7 @@ namespace &defaultHeapProperties, D3D12_HEAP_FLAG_NONE, &descCopy, - D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_RESOLVE_DEST, nullptr, IID_GRAPHICS_PPV_ARGS(pTemp.GetAddressOf())); if (FAILED(hr)) @@ -267,6 +270,11 @@ namespace } copySource = pTemp; + beforeState = D3D12_RESOURCE_STATE_RESOLVE_DEST; + } + else + { + beforeStateSource = D3D12_RESOURCE_STATE_COPY_SOURCE; } // Create a staging texture @@ -283,7 +291,7 @@ namespace assert(*pStaging); // Transition the resource if necessary - TransitionResource(commandList.Get(), pSource, beforeState, D3D12_RESOURCE_STATE_COPY_SOURCE); + TransitionResource(commandList.Get(), copySource.Get(), beforeState, D3D12_RESOURCE_STATE_COPY_SOURCE); // Get the copy target location for (UINT j = 0; j < numberOfResources; ++j) @@ -293,8 +301,8 @@ namespace commandList->CopyTextureRegion(©Dest, 0, 0, 0, ©Src, nullptr); } - // Transition the resource to the next state - TransitionResource(commandList.Get(), pSource, D3D12_RESOURCE_STATE_COPY_SOURCE, afterState); + // Transition the source resource to the next state + TransitionResource(commandList.Get(), pSource, beforeStateSource, afterState); hr = commandList->Close(); if (FAILED(hr)) diff --git a/ScreenGrab/ScreenGrab11.cpp b/ScreenGrab/ScreenGrab11.cpp index 75645a3..c915f1a 100644 --- a/ScreenGrab/ScreenGrab11.cpp +++ b/ScreenGrab/ScreenGrab11.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -69,9 +70,9 @@ using Microsoft::WRL::ComPtr; //-------------------------------------------------------------------------------------- namespace { -#pragma pack(push,1) + #pragma pack(push,1) -#define DDS_MAGIC 0x20534444 // "DDS " + constexpr uint32_t DDS_MAGIC = 0x20534444; // "DDS " struct DDS_PIXELFORMAT { @@ -85,20 +86,20 @@ namespace 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_ALPHA 0x00000002 // DDPF_ALPHA -#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV + #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_ALPHA 0x00000002 // DDPF_ALPHA + #define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV -#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT -#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT -#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH -#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE + #define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT + #define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT + #define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH + #define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE -#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE + #define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE struct DDS_HEADER { @@ -127,7 +128,15 @@ namespace uint32_t reserved; }; -#pragma pack(pop) + #pragma pack(pop) + + static_assert(sizeof(DDS_PIXELFORMAT) == 32, "DDS pixel format size mismatch"); + 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"); const DDS_PIXELFORMAT DDSPF_DXT1 = { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 }; @@ -816,13 +825,12 @@ HRESULT DirectX::SaveDDSTextureToFile( auto_delete_file delonfail(hFile.get()); // Setup header - constexpr size_t MAX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10); - uint8_t fileHeader[MAX_HEADER_SIZE] = {}; + uint8_t fileHeader[DDS_DX10_HEADER_SIZE] = {}; *reinterpret_cast(&fileHeader[0]) = DDS_MAGIC; auto header = reinterpret_cast(&fileHeader[0] + sizeof(uint32_t)); - size_t headerSize = sizeof(uint32_t) + sizeof(DDS_HEADER); + size_t headerSize = DDS_MIN_HEADER_SIZE; header->size = sizeof(DDS_HEADER); header->flags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP; header->height = desc.Height; @@ -879,7 +887,7 @@ HRESULT DirectX::SaveDDSTextureToFile( memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_DX10, sizeof(DDS_PIXELFORMAT)); headerSize += sizeof(DDS_HEADER_DXT10); - extHeader = reinterpret_cast(fileHeader + sizeof(uint32_t) + sizeof(DDS_HEADER)); + extHeader = reinterpret_cast(fileHeader + DDS_MIN_HEADER_SIZE); extHeader->dxgiFormat = desc.Format; extHeader->resourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D; extHeader->arraySize = 1; diff --git a/ScreenGrab/ScreenGrab12.cpp b/ScreenGrab/ScreenGrab12.cpp index eee5f60..7c19630 100644 --- a/ScreenGrab/ScreenGrab12.cpp +++ b/ScreenGrab/ScreenGrab12.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -93,7 +94,7 @@ namespace { #pragma pack(push,1) -#define DDS_MAGIC 0x20534444 // "DDS " + constexpr uint32_t DDS_MAGIC = 0x20534444; // "DDS " struct DDS_PIXELFORMAT { @@ -107,20 +108,20 @@ namespace 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_ALPHA 0x00000002 // DDPF_ALPHA -#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV + #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_ALPHA 0x00000002 // DDPF_ALPHA + #define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV -#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT -#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT -#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH -#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE + #define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT + #define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT + #define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH + #define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE -#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE + #define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE struct DDS_HEADER { @@ -149,7 +150,15 @@ namespace uint32_t reserved; }; -#pragma pack(pop) + static_assert(sizeof(DDS_PIXELFORMAT) == 32, "DDS pixel format size mismatch"); + static_assert(sizeof(DDS_HEADER) == 124, "DDS Header size mismatch"); + static_assert(sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch"); + + #pragma pack(pop) + + 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"); const DDS_PIXELFORMAT DDSPF_DXT1 = { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 }; @@ -755,8 +764,11 @@ namespace bufferDesc.SampleDesc.Count = 1; ComPtr copySource(pSource); + D3D12_RESOURCE_STATES beforeStateSource = beforeState; if (desc.SampleDesc.Count > 1) { + TransitionResource(commandList.Get(), pSource, beforeState, D3D12_RESOURCE_STATE_RESOLVE_SOURCE); + // MSAA content must be resolved before being copied to a staging texture auto descCopy = desc; descCopy.SampleDesc.Count = 1; @@ -768,7 +780,7 @@ namespace &defaultHeapProperties, D3D12_HEAP_FLAG_NONE, &descCopy, - D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_RESOLVE_DEST, nullptr, IID_ID3D12Resource, reinterpret_cast(pTemp.GetAddressOf())); @@ -797,6 +809,11 @@ namespace } copySource = pTemp; + beforeState = D3D12_RESOURCE_STATE_RESOLVE_DEST; + } + else + { + beforeStateSource = D3D12_RESOURCE_STATE_COPY_SOURCE; } // Create a staging texture @@ -815,7 +832,7 @@ namespace assert(*pStaging); // Transition the resource if necessary - TransitionResource(commandList.Get(), pSource, beforeState, D3D12_RESOURCE_STATE_COPY_SOURCE); + TransitionResource(commandList.Get(), copySource.Get(), beforeState, D3D12_RESOURCE_STATE_COPY_SOURCE); // Get the copy target location D3D12_PLACED_SUBRESOURCE_FOOTPRINT bufferFootprint = {}; @@ -831,8 +848,8 @@ namespace // Copy the texture commandList->CopyTextureRegion(©Dest, 0, 0, 0, ©Src, nullptr); - // Transition the resource to the next state - TransitionResource(commandList.Get(), pSource, D3D12_RESOURCE_STATE_COPY_SOURCE, afterState); + // Transition the source resource to the next state + TransitionResource(commandList.Get(), pSource, beforeStateSource, afterState); hr = commandList->Close(); if (FAILED(hr)) @@ -954,13 +971,12 @@ HRESULT DirectX::SaveDDSTextureToFile( #endif // Setup header - constexpr size_t MAX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10); - uint8_t fileHeader[MAX_HEADER_SIZE] = {}; + uint8_t fileHeader[DDS_DX10_HEADER_SIZE] = {}; *reinterpret_cast(&fileHeader[0]) = DDS_MAGIC; auto header = reinterpret_cast(&fileHeader[0] + sizeof(uint32_t)); - size_t headerSize = sizeof(uint32_t) + sizeof(DDS_HEADER); + size_t headerSize = DDS_MIN_HEADER_SIZE; header->size = sizeof(DDS_HEADER); header->flags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP; header->height = desc.Height; @@ -1017,7 +1033,7 @@ HRESULT DirectX::SaveDDSTextureToFile( memcpy(&header->ddspf, &DDSPF_DX10, sizeof(DDS_PIXELFORMAT)); headerSize += sizeof(DDS_HEADER_DXT10); - extHeader = reinterpret_cast(fileHeader + sizeof(uint32_t) + sizeof(DDS_HEADER)); + extHeader = reinterpret_cast(fileHeader + DDS_MIN_HEADER_SIZE); extHeader->dxgiFormat = desc.Format; extHeader->resourceDimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; extHeader->arraySize = 1; @@ -1422,7 +1438,9 @@ HRESULT DirectX::SaveWICTextureToFile( else { // No conversion required - hr = frame->WritePixels(desc.Height, static_cast(dstRowPitch), static_cast(imageSize), static_cast(pMappedMemory)); + hr = frame->WritePixels(desc.Height, + static_cast(dstRowPitch), static_cast(imageSize), + static_cast(pMappedMemory)); } pStaging->Unmap(0, &writeRange); diff --git a/ScreenGrab/ScreenGrab9.cpp b/ScreenGrab/ScreenGrab9.cpp index 38c4a57..03fa4dc 100644 --- a/ScreenGrab/ScreenGrab9.cpp +++ b/ScreenGrab/ScreenGrab9.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -63,9 +64,9 @@ using Microsoft::WRL::ComPtr; //-------------------------------------------------------------------------------------- namespace { -#pragma pack(push,1) + #pragma pack(push,1) -#define DDS_MAGIC 0x20534444 // "DDS " + constexpr uint32_t DDS_MAGIC = 0x20534444; // "DDS " struct DDS_PIXELFORMAT { @@ -79,22 +80,22 @@ namespace 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_ALPHA 0x00000002 // DDPF_ALPHA -#define DDS_BUMPLUMINANCE 0x00040000 // DDPF_BUMPLUMINANCE -#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV -#define DDS_BUMPDUDVA 0x00080001 // DDPF_BUMPDUDV | DDPF_ALPHAPIXELS + #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_ALPHA 0x00000002 // DDPF_ALPHA + #define DDS_BUMPLUMINANCE 0x00040000 // DDPF_BUMPLUMINANCE + #define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV + #define DDS_BUMPDUDVA 0x00080001 // DDPF_BUMPDUDV | DDPF_ALPHAPIXELS -#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT -#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT -#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH -#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE + #define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT + #define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT + #define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH + #define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE -#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE + #define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE struct DDS_HEADER { @@ -114,7 +115,12 @@ namespace uint32_t reserved2; }; -#pragma pack(pop) + #pragma pack(pop) + + static_assert(sizeof(DDS_PIXELFORMAT) == 32, "DDS pixel format size mismatch"); + static_assert(sizeof(DDS_HEADER) == 124, "DDS Header size mismatch"); + + constexpr size_t DDS_DX9_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER); const DDS_PIXELFORMAT DDSPF_DXT1 = { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 }; @@ -606,13 +612,11 @@ HRESULT DirectX::SaveDDSTextureToFile( auto_delete_file delonfail(hFile.get()); // Setup header - constexpr size_t MAX_HEADER_SIZE = sizeof(uint32_t) + sizeof(DDS_HEADER); - uint8_t fileHeader[MAX_HEADER_SIZE] = {}; + uint8_t fileHeader[DDS_DX9_HEADER_SIZE] = {}; *reinterpret_cast(&fileHeader[0]) = DDS_MAGIC; auto header = reinterpret_cast(&fileHeader[0] + sizeof(uint32_t)); - constexpr size_t headerSize = sizeof(uint32_t) + sizeof(DDS_HEADER); header->size = sizeof(DDS_HEADER); header->flags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP; header->height = desc.Height; @@ -726,10 +730,10 @@ HRESULT DirectX::SaveDDSTextureToFile( // Write header & pixels DWORD bytesWritten; - if (!WriteFile(hFile.get(), fileHeader, static_cast(headerSize), &bytesWritten, nullptr)) + if (!WriteFile(hFile.get(), fileHeader, static_cast(DDS_DX9_HEADER_SIZE), &bytesWritten, nullptr)) return HRESULT_FROM_WIN32(GetLastError()); - if (bytesWritten != headerSize) + if (bytesWritten != DDS_DX9_HEADER_SIZE) return E_FAIL; if (!WriteFile(hFile.get(), pixels.get(), static_cast(slicePitch), &bytesWritten, nullptr))