Canonical LGPL-3.0-only text, GPL-3.0 companion, SPDX headers on all first-party sources. Vendored lib/ (GDeflate, libdeflate) untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
54 lines
2.3 KiB
C++
54 lines
2.3 KiB
C++
//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<std::byte> bytes;
|
|
std::vector<RegionMeta> 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<const std::span<const std::byte>> 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<const std::span<std::byte>> 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);
|
|
}
|