From 2bd367a4dc26f8e3b22298c91b9a5680833d4c95 Mon Sep 17 00:00:00 2001 From: mpersano Date: Sat, 27 Feb 2016 20:45:16 -0300 Subject: [PATCH] Add support for compressing texture arrays. Also add support for reading/writing DX10 uncompressed (RGB/lumi) textures, so now it's possible to compress a texture array assembled with nvcompress. --- src/nvimage/DirectDrawSurface.cpp | 147 +++++++++++++++++++----------- src/nvimage/DirectDrawSurface.h | 17 +++- src/nvtt/Context.cpp | 49 +++++----- src/nvtt/Context.h | 2 +- src/nvtt/InputOptions.cpp | 15 ++- src/nvtt/nvtt.h | 5 +- src/nvtt/tests/cubemaptest.cpp | 2 +- src/nvtt/tools/compress.cpp | 9 +- 8 files changed, 160 insertions(+), 86 deletions(-) diff --git a/src/nvimage/DirectDrawSurface.cpp b/src/nvimage/DirectDrawSurface.cpp index 8191f64..3be26b9 100644 --- a/src/nvimage/DirectDrawSurface.cpp +++ b/src/nvimage/DirectDrawSurface.cpp @@ -427,60 +427,85 @@ namespace { struct FormatDescriptor { - uint format; - uint bitcount; - uint rmask; - uint gmask; - uint bmask; - uint amask; + uint d3d9Format; + uint dxgiFormat; + RGBAPixelFormat pixelFormat; }; - static const FormatDescriptor s_d3d9Formats[] = + static const FormatDescriptor s_formats[] = { - { D3DFMT_R8G8B8, 24, 0xFF0000, 0xFF00, 0xFF, 0 }, - { D3DFMT_A8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000 }, // DXGI_FORMAT_B8G8R8A8_UNORM - { D3DFMT_X8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0 }, // DXGI_FORMAT_B8G8R8X8_UNORM - { D3DFMT_R5G6B5, 16, 0xF800, 0x7E0, 0x1F, 0 }, // DXGI_FORMAT_B5G6R5_UNORM - { D3DFMT_X1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0 }, - { D3DFMT_A1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0x8000 }, // DXGI_FORMAT_B5G5R5A1_UNORM - { D3DFMT_A4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0xF000 }, - { D3DFMT_R3G3B2, 8, 0xE0, 0x1C, 0x3, 0 }, - { D3DFMT_A8, 8, 0, 0, 0, 8 }, // DXGI_FORMAT_A8_UNORM - { D3DFMT_A8R3G3B2, 16, 0xE0, 0x1C, 0x3, 0xFF00 }, - { D3DFMT_X4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0 }, - { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, // DXGI_FORMAT_R10G10B10A2 - { D3DFMT_A8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 }, // DXGI_FORMAT_R8G8B8A8_UNORM - { D3DFMT_X8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0 }, - { D3DFMT_G16R16, 32, 0xFFFF, 0xFFFF0000, 0, 0 }, // DXGI_FORMAT_R16G16_UNORM - { D3DFMT_A2R10G10B10, 32, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000 }, - { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, - - { D3DFMT_L8, 8, 0xFF, 0, 0, 0 }, // DXGI_FORMAT_R8_UNORM - { D3DFMT_L16, 16, 0xFFFF, 0, 0, 0 }, // DXGI_FORMAT_R16_UNORM - { D3DFMT_A8L8, 16, 0xFF, 0, 0, 0xFF00 }, // DXGI_FORMAT_R8G8_UNORM? + { D3DFMT_R8G8B8, DXGI_FORMAT_UNKNOWN, { 24, 0xFF0000, 0xFF00, 0xFF, 0 } }, + { D3DFMT_A8R8G8B8, DXGI_FORMAT_B8G8R8A8_UNORM, { 32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000 } }, + { D3DFMT_X8R8G8B8, DXGI_FORMAT_B8G8R8X8_UNORM, { 32, 0xFF0000, 0xFF00, 0xFF, 0 } }, + { D3DFMT_R5G6B5, DXGI_FORMAT_B5G6R5_UNORM, { 16, 0xF800, 0x7E0, 0x1F, 0 } }, + { D3DFMT_X1R5G5B5, DXGI_FORMAT_UNKNOWN, { 16, 0x7C00, 0x3E0, 0x1F, 0 } }, + { D3DFMT_A1R5G5B5, DXGI_FORMAT_B5G5R5A1_UNORM, { 16, 0x7C00, 0x3E0, 0x1F, 0x8000 } }, + { D3DFMT_A4R4G4B4, DXGI_FORMAT_UNKNOWN, { 16, 0xF00, 0xF0, 0xF, 0xF000 } }, + { D3DFMT_R3G3B2, DXGI_FORMAT_UNKNOWN, { 8, 0xE0, 0x1C, 0x3, 0 } }, + { D3DFMT_A8, DXGI_FORMAT_A8_UNORM, { 8, 0, 0, 0, 8 } }, + { D3DFMT_A8R3G3B2, DXGI_FORMAT_UNKNOWN, { 16, 0xE0, 0x1C, 0x3, 0xFF00 } }, + { D3DFMT_X4R4G4B4, DXGI_FORMAT_UNKNOWN, { 16, 0xF00, 0xF0, 0xF, 0 } }, + { D3DFMT_A2B10G10R10, DXGI_FORMAT_R10G10B10A2_UNORM, { 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 } }, + { D3DFMT_A8B8G8R8, DXGI_FORMAT_R8G8B8A8_UNORM, { 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 } }, + { D3DFMT_X8B8G8R8, DXGI_FORMAT_UNKNOWN, { 32, 0xFF, 0xFF00, 0xFF0000, 0 } }, + { D3DFMT_G16R16, DXGI_FORMAT_R16G16_UNORM, { 32, 0xFFFF, 0xFFFF0000, 0, 0 } }, + { D3DFMT_A2R10G10B10, DXGI_FORMAT_UNKNOWN, { 32, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000 } }, + { D3DFMT_A2B10G10R10, DXGI_FORMAT_UNKNOWN, { 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 } }, + + { D3DFMT_L8, DXGI_FORMAT_R8_UNORM , { 8, 0xFF, 0, 0, 0 } }, + { D3DFMT_L16, DXGI_FORMAT_R16_UNORM, { 16, 0xFFFF, 0, 0, 0 } }, + { D3DFMT_A8L8, DXGI_FORMAT_R8G8_UNORM, { 16, 0xFF, 0, 0, 0xFF00 } }, }; - static const uint s_d3d9FormatCount = NV_ARRAY_SIZE(s_d3d9Formats); + static const uint s_formatCount = NV_ARRAY_SIZE(s_formats); } // namespace uint nv::findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) { - for (int i = 0; i < s_d3d9FormatCount; i++) + for (int i = 0; i < s_formatCount; i++) { - if (s_d3d9Formats[i].bitcount == bitcount && - s_d3d9Formats[i].rmask == rmask && - s_d3d9Formats[i].gmask == gmask && - s_d3d9Formats[i].bmask == bmask && - s_d3d9Formats[i].amask == amask) + if (s_formats[i].pixelFormat.bitcount == bitcount && + s_formats[i].pixelFormat.rmask == rmask && + s_formats[i].pixelFormat.gmask == gmask && + s_formats[i].pixelFormat.bmask == bmask && + s_formats[i].pixelFormat.amask == amask) { - return s_d3d9Formats[i].format; + return s_formats[i].d3d9Format; } } return 0; } +uint nv::findDXGIFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) +{ + for (int i = 0; i < s_formatCount; i++) + { + if (s_formats[i].pixelFormat.bitcount == bitcount && + s_formats[i].pixelFormat.rmask == rmask && + s_formats[i].pixelFormat.gmask == gmask && + s_formats[i].pixelFormat.bmask == bmask && + s_formats[i].pixelFormat.amask == amask) + { + return s_formats[i].dxgiFormat; + } + } + + return DXGI_FORMAT_UNKNOWN; +} + +const RGBAPixelFormat *nv::findDXGIPixelFormat(uint dxgiFormat) +{ + for (int i = 0; i < s_formatCount; i++) + { + if (s_formats[i].dxgiFormat == dxgiFormat) { + return &s_formats[i].pixelFormat; + } + } + + return NULL; +} DDSHeader::DDSHeader() { @@ -964,8 +989,9 @@ bool DirectDrawSurface::isSupported() const { return true; } - - return false; + else { + return findDXGIPixelFormat(header.header10.dxgiFormat) != NULL; + } } else { @@ -1072,6 +1098,13 @@ uint DirectDrawSurface::depth() const else return 1; } +uint DirectDrawSurface::arraySize() const +{ + nvDebugCheck(isValid()); + if (header.hasDX10Header()) return header.header10.arraySize; + else return 1; +} + bool DirectDrawSurface::isTexture1D() const { nvDebugCheck(isValid()); @@ -1087,7 +1120,7 @@ bool DirectDrawSurface::isTexture2D() const nvDebugCheck(isValid()); if (header.hasDX10Header()) { - return header.header10.resourceDimension == DDS_DIMENSION_TEXTURE2D; + return header.header10.resourceDimension == DDS_DIMENSION_TEXTURE2D && header.header10.arraySize == 1; } else { @@ -1114,6 +1147,12 @@ bool DirectDrawSurface::isTextureCube() const return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0; } +bool DirectDrawSurface::isTextureArray() const +{ + nvDebugCheck(isValid()); + return header.hasDX10Header() && header.header10.arraySize > 1; +} + void DirectDrawSurface::setNormalFlag(bool b) { nvDebugCheck(isValid()); @@ -1163,14 +1202,18 @@ void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) if (header.hasDX10Header()) { - // So far only block formats supported. - readBlockImage(img); + if (const RGBAPixelFormat *format = findDXGIPixelFormat(header.header10.dxgiFormat)) { + readLinearImage(img, format->bitcount, format->rmask, format->gmask, format->bmask, format->amask); + } + else { + readBlockImage(img); + } } else { if (header.pf.flags & DDPF_RGB) { - readLinearImage(img); + readLinearImage(img, header.pf.bitcount, header.pf.rmask, header.pf.gmask, header.pf.bmask, header.pf.amask); } else if (header.pf.flags & DDPF_FOURCC) { @@ -1248,7 +1291,7 @@ bool DirectDrawSurface::readSurface(uint face, uint mipmap, void * data, uint si } -void DirectDrawSurface::readLinearImage(Image * img) +void DirectDrawSurface::readLinearImage(Image * img, uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) { nvDebugCheck(stream != NULL); nvDebugCheck(img != NULL); @@ -1258,18 +1301,18 @@ void DirectDrawSurface::readLinearImage(Image * img) const uint d = img->depth(); uint rshift, rsize; - PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize); + PixelFormat::maskShiftAndSize(rmask, &rshift, &rsize); uint gshift, gsize; - PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize); + PixelFormat::maskShiftAndSize(gmask, &gshift, &gsize); uint bshift, bsize; - PixelFormat::maskShiftAndSize(header.pf.bmask, &bshift, &bsize); + PixelFormat::maskShiftAndSize(bmask, &bshift, &bsize); uint ashift, asize; - PixelFormat::maskShiftAndSize(header.pf.amask, &ashift, &asize); + PixelFormat::maskShiftAndSize(amask, &ashift, &asize); - uint byteCount = (header.pf.bitcount + 7) / 8; + uint byteCount = (bitcount + 7) / 8; #pragma NV_MESSAGE("TODO: Support floating point linear images and other FOURCC codes.") @@ -1284,10 +1327,10 @@ void DirectDrawSurface::readLinearImage(Image * img) stream->serialize(&c, byteCount); Color32 pixel(0, 0, 0, 0xFF); - pixel.r = PixelFormat::convert((c & header.pf.rmask) >> rshift, rsize, 8); - pixel.g = PixelFormat::convert((c & header.pf.gmask) >> gshift, gsize, 8); - pixel.b = PixelFormat::convert((c & header.pf.bmask) >> bshift, bsize, 8); - pixel.a = PixelFormat::convert((c & header.pf.amask) >> ashift, asize, 8); + pixel.r = PixelFormat::convert((c & rmask) >> rshift, rsize, 8); + pixel.g = PixelFormat::convert((c & gmask) >> gshift, gsize, 8); + pixel.b = PixelFormat::convert((c & bmask) >> bshift, bsize, 8); + pixel.a = PixelFormat::convert((c & amask) >> ashift, asize, 8); img->pixel(x, y, z) = pixel; } diff --git a/src/nvimage/DirectDrawSurface.h b/src/nvimage/DirectDrawSurface.h index bae104b..5b48a8c 100644 --- a/src/nvimage/DirectDrawSurface.h +++ b/src/nvimage/DirectDrawSurface.h @@ -263,9 +263,20 @@ namespace nv DXGI_FORMAT_BC7_UNORM_SRGB = 99, }; + extern uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask); + extern uint findDXGIFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask); - extern uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask); + struct RGBAPixelFormat + { + uint bitcount; + uint rmask; + uint gmask; + uint bmask; + uint amask; + }; + + extern const RGBAPixelFormat *findDXGIPixelFormat(uint dxgiFormat); struct NVIMAGE_CLASS DDSPixelFormat { @@ -377,10 +388,12 @@ namespace nv uint width() const; uint height() const; uint depth() const; + uint arraySize() const; bool isTexture1D() const; bool isTexture2D() const; bool isTexture3D() const; bool isTextureCube() const; + bool isTextureArray() const; void setNormalFlag(bool b); void setHasAlphaFlag(bool b); @@ -404,7 +417,7 @@ namespace nv uint faceSize() const; uint offset(uint face, uint mipmap); - void readLinearImage(Image * img); + void readLinearImage(Image * img, uint bitcount, uint rmask, uint gmask, uint bmask, uint amask); void readBlockImage(Image * img); void readBlock(ColorBlock * rgba); diff --git a/src/nvtt/Context.cpp b/src/nvtt/Context.cpp index b1b6e6f..82759c2 100644 --- a/src/nvtt/Context.cpp +++ b/src/nvtt/Context.cpp @@ -135,7 +135,7 @@ int Compressor::estimateSize(const InputOptions & inputOptions, const Compressio // Surface API. bool Compressor::outputHeader(const Surface & tex, int mipmapCount, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const { - return m.outputHeader(tex.type(), tex.width(), tex.height(), tex.depth(), mipmapCount, tex.isNormalMap(), compressionOptions.m, outputOptions.m); + return m.outputHeader(tex.type(), tex.width(), tex.height(), tex.depth(), 1, mipmapCount, tex.isNormalMap(), compressionOptions.m, outputOptions.m); } bool Compressor::compress(const Surface & tex, int face, int mipmap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const @@ -154,7 +154,7 @@ int Compressor::estimateSize(const Surface & tex, int mipmapCount, const Compres bool Compressor::outputHeader(const CubeSurface & cube, int mipmapCount, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const { - return m.outputHeader(TextureType_Cube, cube.edgeLength(), cube.edgeLength(), 1, mipmapCount, false, compressionOptions.m, outputOptions.m); + return m.outputHeader(TextureType_Cube, cube.edgeLength(), cube.edgeLength(), 1, 1, mipmapCount, false, compressionOptions.m, outputOptions.m); } bool Compressor::compress(const CubeSurface & cube, int mipmap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const @@ -174,9 +174,9 @@ int Compressor::estimateSize(const CubeSurface & cube, int mipmapCount, const Co // Raw API. -bool Compressor::outputHeader(TextureType type, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const +bool Compressor::outputHeader(TextureType type, int w, int h, int d, int arraySize, int mipmapCount, bool isNormalMap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const { - return m.outputHeader(type, w, h, d, mipmapCount, isNormalMap, compressionOptions.m, outputOptions.m); + return m.outputHeader(type, w, h, d, arraySize, mipmapCount, isNormalMap, compressionOptions.m, outputOptions.m); } bool Compressor::compress(int w, int h, int d, int face, int mipmap, const float * rgba, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const @@ -231,6 +231,7 @@ bool Compressor::Private::compress(const InputOptions::Private & inputOptions, c int width = inputOptions.width; int height = inputOptions.height; int depth = inputOptions.depth; + int arraySize = inputOptions.textureType == TextureType_Array ? faceCount : 1; nv::getTargetExtent(&width, &height, &depth, inputOptions.maxExtent, inputOptions.roundMode, inputOptions.textureType); @@ -243,7 +244,7 @@ bool Compressor::Private::compress(const InputOptions::Private & inputOptions, c if (inputOptions.maxLevel > 0) mipmapCount = min(mipmapCount, inputOptions.maxLevel); } - if (!outputHeader(inputOptions.textureType, width, height, depth, mipmapCount, img.isNormalMap(), compressionOptions, outputOptions)) { + if (!outputHeader(inputOptions.textureType, width, height, depth, arraySize, mipmapCount, img.isNormalMap(), compressionOptions, outputOptions)) { return false; } @@ -403,10 +404,9 @@ void Compressor::Private::quantize(Surface & img, const CompressionOptions::Priv } } - -bool Compressor::Private::outputHeader(nvtt::TextureType textureType, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const +bool Compressor::Private::outputHeader(nvtt::TextureType textureType, int w, int h, int d, int arraySize, int mipmapCount, bool isNormalMap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const { - if (w <= 0 || h <= 0 || d <= 0 || mipmapCount <= 0) + if (w <= 0 || h <= 0 || d <= 0 || arraySize <= 0 || mipmapCount <= 0) { outputOptions.error(Error_InvalidInput); return false; @@ -425,15 +425,21 @@ bool Compressor::Private::outputHeader(nvtt::TextureType textureType, int w, int header.setUserVersion(outputOptions.version); if (textureType == TextureType_2D) { + nvCheck(arraySize == 1); header.setTexture2D(); } else if (textureType == TextureType_Cube) { + nvCheck(arraySize == 1); header.setTextureCube(); } else if (textureType == TextureType_3D) { + nvCheck(arraySize == 1); header.setTexture3D(); header.setDepth(d); } + else if (textureType == TextureType_Array) { + header.setTextureArray(arraySize); + } header.setWidth(w); header.setHeight(h); @@ -459,26 +465,23 @@ bool Compressor::Private::outputHeader(nvtt::TextureType textureType, int w, int } } else { - if (bitcount == 16) { - if (compressionOptions.rsize == 16) { - header.setDX10Format(DXGI_FORMAT_R16_UNORM); + if (bitcount == 16 && compressionOptions.rsize == 16) { + header.setDX10Format(DXGI_FORMAT_R16_UNORM); + } + else { + uint format = findDXGIFormat(compressionOptions.bitcount, + compressionOptions.rmask, + compressionOptions.gmask, + compressionOptions.bmask, + compressionOptions.amask); + + if (format != DXGI_FORMAT_UNKNOWN) { + header.setDX10Format(format); } else { - // B5G6R5_UNORM - // B5G5R5A1_UNORM supported = false; } } - else if (bitcount == 32) { - // B8G8R8A8_UNORM - // B8G8R8X8_UNORM - // R8G8B8A8_UNORM - // R10G10B10A2_UNORM - supported = false; - } - else { - supported = false; - } } } else diff --git a/src/nvtt/Context.h b/src/nvtt/Context.h index 7faa447..c497bb1 100644 --- a/src/nvtt/Context.h +++ b/src/nvtt/Context.h @@ -51,7 +51,7 @@ namespace nvtt void quantize(Surface & tex, const CompressionOptions::Private & compressionOptions) const; - bool outputHeader(nvtt::TextureType textureType, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; + bool outputHeader(nvtt::TextureType textureType, int w, int h, int d, int faceCount, int mipmapCount, bool isNormalMap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; nv::CompressorInterface * chooseCpuCompressor(const CompressionOptions::Private & compressionOptions) const; nv::CompressorInterface * chooseGpuCompressor(const CompressionOptions::Private & compressionOptions) const; diff --git a/src/nvtt/InputOptions.cpp b/src/nvtt/InputOptions.cpp index 33c09e6..8179799 100644 --- a/src/nvtt/InputOptions.cpp +++ b/src/nvtt/InputOptions.cpp @@ -124,17 +124,19 @@ void InputOptions::reset() // Setup the input image. -void InputOptions::setTextureLayout(TextureType type, int width, int height, int depth /*= 1*/) +void InputOptions::setTextureLayout(TextureType type, int width, int height, int depth /*= 1*/, int arraySize /*= 1*/) { // Validate arguments. nvCheck(width >= 0); nvCheck(height >= 0); nvCheck(depth >= 0); + nvCheck(arraySize >= 0); // Correct arguments. if (width == 0) width = 1; if (height == 0) height = 1; if (depth == 0) depth = 1; + if (arraySize == 0) arraySize = 1; // Delete previous images. resetTextureLayout(); @@ -145,7 +147,16 @@ void InputOptions::setTextureLayout(TextureType type, int width, int height, int m.depth = depth; // Allocate images. - m.faceCount = (type == TextureType_Cube) ? 6 : 1; + if (type == TextureType_Cube) { + nvCheck(arraySize == 1); + m.faceCount = 6; + } + else if (type == TextureType_Array) { + m.faceCount = arraySize; + } else { + nvCheck(arraySize == 1); + m.faceCount = 1; + } m.mipmapCount = countMipmaps(width, height, depth); m.imageCount = m.mipmapCount * m.faceCount; m.images = new void *[m.imageCount]; diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index 3e261b6..f2b27ce 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -205,6 +205,7 @@ namespace nvtt TextureType_2D, TextureType_Cube, TextureType_3D, + TextureType_Array, }; // Input formats. @@ -266,7 +267,7 @@ namespace nvtt NVTT_API void reset(); // Setup input layout. - NVTT_API void setTextureLayout(TextureType type, int w, int h, int d = 1); + NVTT_API void setTextureLayout(TextureType type, int w, int h, int d = 1, int arraySize = 1); NVTT_API void resetTextureLayout(); // Set mipmap data. Copies the data. @@ -412,7 +413,7 @@ namespace nvtt NVTT_API int estimateSize(const CubeSurface & cube, int mipmapCount, const CompressionOptions & compressionOptions) const; // Raw API. (New in NVTT 2.1) - NVTT_API bool outputHeader(TextureType type, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const; + NVTT_API bool outputHeader(TextureType type, int w, int h, int d, int arraySize, int mipmapCount, bool isNormalMap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const; NVTT_API bool compress(int w, int h, int d, int face, int mipmap, const float * rgba, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const; NVTT_API int estimateSize(int w, int h, int d, int mipmapCount, const CompressionOptions & compressionOptions) const; }; diff --git a/src/nvtt/tests/cubemaptest.cpp b/src/nvtt/tests/cubemaptest.cpp index a835be4..572c7bb 100644 --- a/src/nvtt/tests/cubemaptest.cpp +++ b/src/nvtt/tests/cubemaptest.cpp @@ -76,7 +76,7 @@ int main(int argc, char *argv[]) float topPower = 64; // Output header. - context.outputHeader(nvtt::TextureType_Cube, topSize >> firstMipmap, topSize >> firstMipmap, 1, mipmapCount-firstMipmap, false, compressionOptions, outputOptions); + context.outputHeader(nvtt::TextureType_Cube, topSize >> firstMipmap, topSize >> firstMipmap, 1, 1, mipmapCount-firstMipmap, false, compressionOptions, outputOptions); nv::Timer timer; timer.start(); diff --git a/src/nvtt/tools/compress.cpp b/src/nvtt/tools/compress.cpp index 86979a1..412ba5a 100644 --- a/src/nvtt/tools/compress.cpp +++ b/src/nvtt/tools/compress.cpp @@ -487,11 +487,14 @@ int main(int argc, char *argv[]) nvDebugBreak(); } - else - { - nvDebugCheck(dds.isTextureCube()); + else if (dds.isTextureCube()) { inputOptions.setTextureLayout(nvtt::TextureType_Cube, dds.width(), dds.height()); faceCount = 6; + } else { + nvDebugCheck(dds.isTextureArray()); + inputOptions.setTextureLayout(nvtt::TextureType_Array, dds.width(), dds.height(), 1, dds.arraySize()); + faceCount = dds.arraySize(); + dds10 = true; } uint mipmapCount = dds.mipmapCount();