diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index 8570724..4047ac6 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -513,6 +513,53 @@ namespace DirectX size_t m_size; }; + //--------------------------------------------------------------------------------- + // Tiling utilities + + struct DIRECTX_TEX_API TileShape + { + size_t width; + size_t height; + size_t depth; + + TileShape() = default; + + #if defined(__d3d11_2_h__) || defined(__d3d11_x_h__) + TileShape(const D3D11_TILE_SHAPE& tile) : + width(tile.WidthInTexels), + height(tile.HeightInTexels), + depth(tile.DepthInTexels) + { + } + + void GetTileShape11(D3D11_TILE_SHAPE& tile) const + { + tile.WidthInTexels = static_cast(width); + tile.HeightInTexels = static_cast(height); + tile.DepthInTexels = static_cast(depth); + } + #endif + + #if defined(__d3d12_h__) || defined(__d3d12_x_h__) || defined(__XBOX_D3D12_X__) + TileShape(const D3D12_TILE_SHAPE& tile) : + width(tile.WidthInTexels), + height(tile.HeightInTexels), + depth(tile.DepthInTexels) + { + } + + void GetTileShape12(D3D12_TILE_SHAPE& tile) const + { + tile.WidthInTexels = static_cast(width); + tile.HeightInTexels = static_cast(height); + tile.DepthInTexels = static_cast(depth); + } + #endif + }; + + DIRECTX_TEX_API HRESULT __cdecl ComputeTileShape(_In_ DXGI_FORMAT fmt, _In_ TEX_DIMENSION dimension, + _Out_ TileShape& tiling) noexcept; + //--------------------------------------------------------------------------------- // Image I/O diff --git a/DirectXTex/DirectXTexP.h b/DirectXTex/DirectXTexP.h index a806752..6e930be 100644 --- a/DirectXTex/DirectXTexP.h +++ b/DirectXTex/DirectXTexP.h @@ -132,7 +132,7 @@ #endif #include #else -#include +#include #endif #else // !WIN32 #include diff --git a/DirectXTex/DirectXTexUtil.cpp b/DirectXTex/DirectXTexUtil.cpp index 58eaebf..b268e6a 100644 --- a/DirectXTex/DirectXTexUtil.cpp +++ b/DirectXTex/DirectXTexUtil.cpp @@ -1246,6 +1246,163 @@ size_t DirectX::ComputeScanlines(DXGI_FORMAT fmt, size_t height) noexcept } +//------------------------------------------------------------------------------------- +// Compute standard tile shape for 64KB tiles +//------------------------------------------------------------------------------------- +namespace +{ + constexpr size_t TILED_RESOURCE_TILE_SIZE_IN_BYTES = 65536; +} + +_Use_decl_annotations_ +HRESULT DirectX::ComputeTileShape( + DXGI_FORMAT fmt, + TEX_DIMENSION dimension, + TileShape& tiling) noexcept +{ + tiling = {}; + + if (IsVideo(fmt) || IsPacked(fmt)) + return E_INVALIDARG; + + const size_t bpp = BitsPerPixel(fmt); + if (!bpp || bpp == 1 || bpp == 24 || bpp == 96) + return E_INVALIDARG; + + const bool iscompressed = IsCompressed(fmt); + + switch(dimension) + { + case TEX_DIMENSION_TEXTURE1D: + if (iscompressed) + return E_INVALIDARG; + + tiling.width = (bpp) ? ((TILED_RESOURCE_TILE_SIZE_IN_BYTES * 8) / bpp) : TILED_RESOURCE_TILE_SIZE_IN_BYTES; + tiling.height = tiling.depth = 1; + break; + + case TEX_DIMENSION_TEXTURE2D: + tiling.depth = 1; + if(iscompressed) + { + size_t bpb = BytesPerBlock(fmt); + switch(bpb) + { + case 8: + tiling.width = 128 * 4; + tiling.height = 64 * 4; + break; + + case 16: + tiling.width = tiling.height = 64 * 4; + break; + + default: + return E_INVALIDARG; + } + + assert(((tiling.width / 4) * (tiling.height / 4) * bpb) == TILED_RESOURCE_TILE_SIZE_IN_BYTES); + } + else + { + if (bpp <= 8) + { + tiling.width = tiling.height = 256; + } + else if (bpp <= 16) + { + tiling.width = 256; + tiling.height = 128; + } + else if (bpp <= 32) + { + tiling.width = tiling.height = 128; + } + else if (bpp <= 64) + { + tiling.width = 128; + tiling.height = 64; + } + else if (bpp <= 128) + { + tiling.width = tiling.height = 64; + } + else + { + tiling = {}; + return E_INVALIDARG; + } + + assert(((tiling.width * tiling.height * bpp) / 8) == TILED_RESOURCE_TILE_SIZE_IN_BYTES); + } + break; + + case TEX_DIMENSION_TEXTURE3D: + if(iscompressed) + { + size_t bpb = BytesPerBlock(fmt); + switch(bpb) + { + case 8: + tiling.width = 32 * 4; + tiling.height = 16 * 4; + tiling.depth = 16; + break; + + case 16: + tiling.width = tiling.height = 16 * 4; + tiling.depth = 16; + break; + + default: + return E_INVALIDARG; + } + + assert(((tiling.width / 4) * (tiling.height / 4) * tiling.depth * bpb) == TILED_RESOURCE_TILE_SIZE_IN_BYTES); + } + else + { + if (bpp <= 8) + { + tiling.width = 64; + tiling.height = tiling.depth = 32; + } + else if (bpp <= 16) + { + tiling.width = tiling.height = tiling.depth = 32; + } + else if (bpp <= 32) + { + tiling.width = tiling.height = 32; + tiling.depth = 16; + } + else if (bpp <= 64) + { + tiling.width = 32; + tiling.height = tiling.depth = 16; + } + else if (bpp <= 128) + { + tiling.width = tiling.height = tiling.depth = 16; + } + else + { + tiling = {}; + return E_INVALIDARG; + } + + assert(((tiling.width * tiling.height * tiling.depth * bpp) / 8) == TILED_RESOURCE_TILE_SIZE_IN_BYTES); + } + break; + + default: + return E_INVALIDARG; + } + + return S_OK; +} + + //------------------------------------------------------------------------------------- // Converts to an SRGB equivalent type if available //-------------------------------------------------------------------------------------