//SPDX-License-Identifier: LGPL-3.0-only //SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® export module Crafter.Asset:Compression; import std; export namespace Crafter::Compression { // Hard-aborts the process after printing `msg`. Used in place of // `throw std::runtime_error(...)` so the module is buildable under // `-fno-exceptions` (wasm targets ship without the C++ unwinding // runtime). Asset-loading errors are unrecoverable in practice — a // bad magic, version mismatch, or stream-size mismatch always means // the build's data is inconsistent with the binary. [[noreturn]] inline void Fatal(std::string_view msg) { std::println(std::cerr, "Crafter.Asset fatal: {}", msg); std::abort(); } // One independently-decompressable GDeflate stream inside CompressedBlob::bytes. // Layout matches what VK_EXT_memory_decompression's VkDecompressMemoryRegionEXT // expects, minus the device addresses (which the consumer fills in). struct RegionMeta { std::uint64_t srcOffset; std::uint64_t compressedSize; std::uint64_t decompressedSize; }; struct CompressedBlob { std::vector bytes; std::vector regions; std::uint64_t TotalDecompressedSize() const noexcept { std::uint64_t sum = 0; for (const RegionMeta& r : regions) sum += r.decompressedSize; return sum; } }; // Compresses each input span as its own GDeflate tile-stream; concatenates // them into one byte buffer with a parallel region table. Streams are // independent and can be addressed individually by VkDecompressMemoryRegionEXT // entries on the GPU path. CompressedBlob CompressStreams(std::span> streams); // CPU fallback decoder. outputs.size() must equal blob.regions.size(); // outputs[i].size() must equal blob.regions[i].decompressedSize. void DecompressCPU(const CompressedBlob& blob, std::span> outputs); // Length-prefixed serialization of a CompressedBlob. Used by per-asset // SaveCompressed/LoadCompressed implementations after they've written // their own type-specific header. void WriteBlob(std::ostream& file, const CompressedBlob& blob); CompressedBlob ReadBlob(std::istream& file); }