| 620 | } |
| 621 | |
| 622 | void ImageIO::saveToDDS(const std::filesystem::path& path, const Bitmap& bitmap, CompressionMode mode, bool generateMips) |
| 623 | { |
| 624 | if (!hasExtension(path, "dds")) |
| 625 | { |
| 626 | logWarning("Saving DDS image to '{}' which does not have 'dds' file extension.", path); |
| 627 | } |
| 628 | |
| 629 | try |
| 630 | { |
| 631 | ExportData image; |
| 632 | image.type = nvtt::TextureType::TextureType_2D; |
| 633 | image.width = bitmap.getWidth(); |
| 634 | image.height = bitmap.getHeight(); |
| 635 | image.depth = 1; |
| 636 | image.format = bitmap.getFormat(); |
| 637 | image.faceCount = 1; |
| 638 | image.mipLevels = generateMips ? nvtt::countMipmaps(image.width, image.height, image.depth) : 1; |
| 639 | |
| 640 | if (getFormatChannelCount(image.format) == 2 && mode != CompressionMode::BC5) |
| 641 | { |
| 642 | FALCOR_THROW("Only BC5 compression is supported for two channel images."); |
| 643 | } |
| 644 | |
| 645 | // The DX spec requires the dimensions of BC encoded textures to be a multiple of 4 at the base resolution. |
| 646 | // If the texture has already been rescaled to meet this requirement, skip clamping. |
| 647 | if (generateMips && (mode != CompressionMode::None)) |
| 648 | { |
| 649 | bool clamped = clampIfNeeded(image); |
| 650 | if (clamped) |
| 651 | { |
| 652 | logWarning("Saving DDS image to '{}' with clamped image dimensions to accomodate mipmaps and compression.", path); |
| 653 | } |
| 654 | } |
| 655 | |
| 656 | uint32_t srcWidth = bitmap.getWidth(); |
| 657 | uint32_t srcHeight = bitmap.getHeight(); |
| 658 | |
| 659 | nvtt::Surface surface; |
| 660 | FormatType type = getFormatType(image.format); |
| 661 | if (type == FormatType::Sint || type == FormatType::Snorm) |
| 662 | { |
| 663 | setImage<int8_t>(bitmap.getData(), surface, image, srcWidth, srcHeight, image.depth); |
| 664 | } |
| 665 | else if (type == FormatType::Uint || type == FormatType::Unorm || type == FormatType::UnormSrgb) |
| 666 | { |
| 667 | setImage<uint8_t>(bitmap.getData(), surface, image, srcWidth, srcHeight, image.depth); |
| 668 | } |
| 669 | else if (type == FormatType::Float) |
| 670 | { |
| 671 | if (getNumChannelBits(image.format, 0) == 16) |
| 672 | { |
| 673 | setImage<float16_t>(bitmap.getData(), surface, image, srcWidth, srcHeight, image.depth); |
| 674 | } |
| 675 | else if (getNumChannelBits(image.format, 0) == 32) |
| 676 | { |
| 677 | setImage<float>(bitmap.getData(), surface, image, srcWidth, srcHeight, image.depth); |
| 678 | } |
| 679 | } |
nothing calls this directly
no test coverage detected