|
30 | 30 | #include <limits>
|
31 | 31 | #include <math.h>
|
32 | 32 | #include <vector>
|
| 33 | +#include <array> |
33 | 34 |
|
34 | 35 | #include "TextureLoaderImpl.hpp"
|
35 | 36 | #include "GraphicsAccessories.hpp"
|
|
43 | 44 | #include "DataBlobImpl.hpp"
|
44 | 45 | #include "Align.hpp"
|
45 | 46 |
|
| 47 | +#define STB_DXT_STATIC |
| 48 | +#define STB_DXT_IMPLEMENTATION |
| 49 | +#include "../../ThirdParty/stb/stb_dxt.h" |
| 50 | + |
46 | 51 | extern "C"
|
47 | 52 | {
|
48 | 53 | Diligent::DECODE_PNG_RESULT Diligent_DecodePng(Diligent::IDataBlob* pSrcPngBits,
|
@@ -194,8 +199,8 @@ void TextureLoaderImpl::LoadFromImage(Image* pImage, const TextureLoadInfo& TexL
|
194 | 199 | {
|
195 | 200 | VERIFY_EXPR(pImage != nullptr);
|
196 | 201 |
|
197 |
| - const auto& ImgDesc = pImage->GetDesc(); |
198 |
| - const auto CompSize = GetValueSize(ImgDesc.ComponentType); |
| 202 | + const ImageDesc& ImgDesc = pImage->GetDesc(); |
| 203 | + const Uint32 CompSize = GetValueSize(ImgDesc.ComponentType); |
199 | 204 |
|
200 | 205 | m_TexDesc.Type = RESOURCE_DIM_TEX_2D;
|
201 | 206 | m_TexDesc.Width = ImgDesc.Width;
|
@@ -335,8 +340,126 @@ void TextureLoaderImpl::LoadFromImage(Image* pImage, const TextureLoadInfo& TexL
|
335 | 340 | }
|
336 | 341 | }
|
337 | 342 | }
|
| 343 | + |
| 344 | + if (TexLoadInfo.CompressMode != TEXTURE_LOAD_COMPRESS_MODE_NONE) |
| 345 | + { |
| 346 | + CompressSubresources(NumComponents, ImgDesc.NumComponents, TexLoadInfo); |
| 347 | + m_pImage.Release(); |
| 348 | + } |
338 | 349 | }
|
339 | 350 |
|
| 351 | +void TextureLoaderImpl::CompressSubresources(Uint32 NumComponents, Uint32 NumSrcComponents, const TextureLoadInfo& TexLoadInfo) |
| 352 | +{ |
| 353 | + TEXTURE_FORMAT CompressedFormat = TEX_FORMAT_UNKNOWN; |
| 354 | + switch (NumComponents) |
| 355 | + { |
| 356 | + case 1: |
| 357 | + CompressedFormat = TEX_FORMAT_BC4_UNORM; |
| 358 | + break; |
| 359 | + |
| 360 | + case 2: |
| 361 | + CompressedFormat = TEX_FORMAT_BC5_UNORM; |
| 362 | + break; |
| 363 | + |
| 364 | + case 4: |
| 365 | + if (NumSrcComponents == 3) |
| 366 | + CompressedFormat = TexLoadInfo.IsSRGB ? TEX_FORMAT_BC1_UNORM_SRGB : TEX_FORMAT_BC1_UNORM; |
| 367 | + else if (NumSrcComponents == 4) |
| 368 | + CompressedFormat = TexLoadInfo.IsSRGB ? TEX_FORMAT_BC3_UNORM_SRGB : TEX_FORMAT_BC3_UNORM; |
| 369 | + else |
| 370 | + UNEXPECTED("Unexpected number of source components ", NumSrcComponents); |
| 371 | + break; |
| 372 | + |
| 373 | + default: |
| 374 | + UNEXPECTED("Unexpected number of components ", NumComponents); |
| 375 | + } |
| 376 | + |
| 377 | + if (CompressedFormat == TEX_FORMAT_UNKNOWN) |
| 378 | + return; |
| 379 | + |
| 380 | + m_TexDesc.Format = CompressedFormat; |
| 381 | + const TextureFormatAttribs& FmtAttribs = GetTextureFormatAttribs(CompressedFormat); |
| 382 | + |
| 383 | + std::vector<std::vector<Uint8>> CompressedMips(m_SubResources.size()); |
| 384 | + for (Uint32 slice = 0; slice < m_TexDesc.GetArraySize(); ++slice) |
| 385 | + { |
| 386 | + for (Uint32 mip = 0; mip < m_TexDesc.MipLevels; ++mip) |
| 387 | + { |
| 388 | + const Uint32 SubResIndex = slice * m_TexDesc.MipLevels + mip; |
| 389 | + TextureSubResData& SubResData = m_SubResources[SubResIndex]; |
| 390 | + std::vector<Uint8>& CompressedMip = CompressedMips[SubResIndex]; |
| 391 | + |
| 392 | + const MipLevelProperties CompressedMipProps = GetMipLevelProperties(m_TexDesc, mip); |
| 393 | + const Uint32 MaxCol = CompressedMipProps.LogicalWidth - 1; |
| 394 | + const Uint32 MaxRow = CompressedMipProps.LogicalHeight - 1; |
| 395 | + const size_t CompressedStride = static_cast<size_t>(CompressedMipProps.RowSize); |
| 396 | + CompressedMip.resize(CompressedStride * CompressedMipProps.StorageHeight); |
| 397 | + |
| 398 | + for (Uint32 row = 0; row < CompressedMipProps.StorageHeight; row += FmtAttribs.BlockHeight) |
| 399 | + { |
| 400 | + const Uint32 row0 = row; |
| 401 | + const Uint32 row1 = std::min(row + 1, MaxRow); |
| 402 | + const Uint32 row2 = std::min(row + 2, MaxRow); |
| 403 | + const Uint32 row3 = std::min(row + 3, MaxRow); |
| 404 | + |
| 405 | + for (Uint32 col = 0; col < CompressedMipProps.StorageWidth; col += FmtAttribs.BlockWidth) |
| 406 | + { |
| 407 | + const Uint32 col0 = col; |
| 408 | + const Uint32 col1 = std::min(col + 1, MaxCol); |
| 409 | + const Uint32 col2 = std::min(col + 2, MaxCol); |
| 410 | + const Uint32 col3 = std::min(col + 3, MaxCol); |
| 411 | + |
| 412 | + auto ReadBlockData = [&](auto& BlockData) { |
| 413 | + using T = typename std::decay_t<decltype(BlockData)>::value_type; |
| 414 | + |
| 415 | + const T* SrcPtr = static_cast<const T*>(SubResData.pData); |
| 416 | + const size_t SrcStride = static_cast<size_t>(SubResData.Stride) / sizeof(T); |
| 417 | + // clang-format off |
| 418 | + BlockData = |
| 419 | + { |
| 420 | + SrcPtr[col0 + SrcStride * row0], SrcPtr[col1 + SrcStride * row0], SrcPtr[col2 + SrcStride * row0], SrcPtr[col3 + SrcStride * row0], |
| 421 | + SrcPtr[col0 + SrcStride * row1], SrcPtr[col1 + SrcStride * row1], SrcPtr[col2 + SrcStride * row1], SrcPtr[col3 + SrcStride * row1], |
| 422 | + SrcPtr[col0 + SrcStride * row2], SrcPtr[col1 + SrcStride * row2], SrcPtr[col2 + SrcStride * row2], SrcPtr[col3 + SrcStride * row2], |
| 423 | + SrcPtr[col0 + SrcStride * row3], SrcPtr[col1 + SrcStride * row3], SrcPtr[col2 + SrcStride * row3], SrcPtr[col3 + SrcStride * row3] |
| 424 | + }; |
| 425 | + // clang-format on |
| 426 | + return reinterpret_cast<const unsigned char*>(BlockData.data()); |
| 427 | + }; |
| 428 | + |
| 429 | + Uint8* pDst = &CompressedMip[(col / FmtAttribs.BlockWidth) * FmtAttribs.ComponentSize + CompressedStride * (row / FmtAttribs.BlockHeight)]; |
| 430 | + if (NumComponents == 1) |
| 431 | + { |
| 432 | + std::array<Uint8, 16> BlockData8; |
| 433 | + stb_compress_bc4_block(pDst, ReadBlockData(BlockData8)); |
| 434 | + } |
| 435 | + else if (NumComponents == 2) |
| 436 | + { |
| 437 | + std::array<Uint16, 16> BlockData16; |
| 438 | + stb_compress_bc5_block(pDst, ReadBlockData(BlockData16)); |
| 439 | + } |
| 440 | + else if (NumComponents == 4) |
| 441 | + { |
| 442 | + std::array<Uint32, 16> BlockData32; |
| 443 | + const int StbDxtMode = (TexLoadInfo.CompressMode == TEXTURE_LOAD_COMPRESS_MODE_BC_HIGH_QUAL) ? STB_DXT_HIGHQUAL : STB_DXT_NORMAL; |
| 444 | + const int StoreAlpha = NumSrcComponents == 4 ? 1 : 0; |
| 445 | + stb_compress_dxt_block(pDst, ReadBlockData(BlockData32), StoreAlpha, StbDxtMode); |
| 446 | + } |
| 447 | + else |
| 448 | + { |
| 449 | + UNEXPECTED("Unexpected number of components"); |
| 450 | + } |
| 451 | + } |
| 452 | + } |
| 453 | + |
| 454 | + SubResData.pData = CompressedMip.data(); |
| 455 | + SubResData.Stride = CompressedStride; |
| 456 | + } |
| 457 | + } |
| 458 | + |
| 459 | + m_TexDesc.Width = AlignUp(m_TexDesc.Width, FmtAttribs.BlockWidth); |
| 460 | + m_TexDesc.Height = AlignUp(m_TexDesc.Height, FmtAttribs.BlockHeight); |
| 461 | + m_Mips.swap(CompressedMips); |
| 462 | +} |
340 | 463 |
|
341 | 464 | void CreateTextureLoaderFromFile(const char* FilePath,
|
342 | 465 | IMAGE_FILE_FORMAT FileFormat,
|
|
0 commit comments