载入中...
搜索中...
未找到
EvpackImageLoader.cpp
浏览该文件的文档.
3
4#include <algorithm>
5#include <limits>
6
7namespace eve::asset_graphics {
8namespace {
9
10std::uint32_t little32(std::span<const std::uint8_t> bytes, std::size_t offset) {
11 return std::uint32_t(bytes[offset]) | (std::uint32_t(bytes[offset + 1]) << 8) |
12 (std::uint32_t(bytes[offset + 2]) << 16) | (std::uint32_t(bytes[offset + 3]) << 24);
13}
14
15} // namespace
16
18 const AssetRef& image, const asset::EvpackCapabilities& capabilities,
19 const ImageAssetLoadLimits& limits) const {
20 auto decoded = asset::decodeEvpackImage(reader_, image, capabilities, limits);
21 if (!decoded) return Result<LoadedGraphicsImage>::failure(decoded.status());
22 auto& value = decoded.value();
23 auto uploaded = value.levels == 1
24 ? factory_.uploadRgba8(value.width, value.height, value.pixels.data(), value.srgb)
25 : factory_.uploadRgba8MipChain(value.width, value.height, value.levels, value.pixels);
26 if (!uploaded) return Result<LoadedGraphicsImage>::failure(uploaded.status());
27 return Result<LoadedGraphicsImage>::success({image, uploaded.value(), std::move(decoded).takeValue().variant});
28}
30 const asset::EvpackCapabilities& capabilities,
32 auto payload = reader_.read(volume, "eve.volume-texture/1", capabilities, limits.maximumDecodedBytes);
34 const asset::RuntimeAssetChunk* definition = nullptr;
35 const asset::RuntimeAssetChunk* bulk = nullptr;
36 for (const auto& chunk : payload.value().chunks) {
37 if (chunk.kind == asset::EvpackChunkKind::Definition) {
38 if (definition)
40 Diagnostic::error(DiagnosticCode::ParseError, "volume texture contains duplicate definitions", {},
41 {}, "asset.graphics.image"));
42 definition = &chunk;
43 } else if (chunk.kind == asset::EvpackChunkKind::Bulk) {
44 if (bulk)
46 Diagnostic::error(DiagnosticCode::ParseError, "volume texture contains duplicate bulk chunks", {},
47 {}, "asset.graphics.image"));
48 bulk = &chunk;
49 }
50 }
51 const uint8_t magic[]{'E', 'V', 'V', 'O', 'L', 0, 1, 0};
52 if (!definition || !bulk || bulk->chunkId != 1 || bulk->bytes.size() < 24 ||
53 !std::equal(std::begin(magic), std::end(magic), bulk->bytes.begin()))
55 Diagnostic::error(DiagnosticCode::ParseError, "EVVOL definition or bulk header is missing or invalid", {},
56 {}, "asset.graphics.image"));
57 const uint32_t width = little32(bulk->bytes, 8), height = little32(bulk->bytes, 12),
58 depth = little32(bulk->bytes, 16), reserved = little32(bulk->bytes, 20);
59 if (!width || !height || !depth || width > limits.maximumDimension || height > limits.maximumDimension ||
60 depth > limits.maximumDimension || uint64_t(width) > std::numeric_limits<uint64_t>::max() / height ||
61 uint64_t(width) * height > std::numeric_limits<uint64_t>::max() / depth)
63 DiagnosticCode::InvalidArgument, "EVVOL dimensions, reserved field or packed bytes are invalid", {}, {},
64 "asset.graphics.image"));
65 const uint64_t voxels = uint64_t(width) * height * depth;
66 if (voxels > limits.maximumVoxels || reserved != 0 || limits.maximumDecodedBytes < 24 ||
67 voxels > (limits.maximumDecodedBytes - 24) / 4 || bulk->bytes.size() != 24 + voxels * 4)
69 DiagnosticCode::InvalidArgument, "EVVOL dimensions, reserved field or packed bytes are invalid", {}, {},
70 "asset.graphics.image"));
71 auto decoded = asset::decodeRuntimeDefinition(definition->bytes);
72 if (!decoded) return Result<LoadedGraphicsVolumeTexture>::failure(decoded.status());
73 const auto* object = decoded.value().getIf<Value::Object>();
74 auto exactInteger = [&](const char* key, uint32_t expected) {
75 if (!object) return false;
76 const auto found = object->find(key);
77 return found != object->end() && found->second.isInt64() && found->second.asInt() == expected;
78 };
79 auto exactString = [&](const char* key, const char* expected) {
80 if (!object) return false;
81 const auto found = object->find(key);
82 return found != object->end() && found->second.isString() && found->second.asString() == expected;
83 };
84 if (!object || object->size() != 8 || !exactInteger("schemaVersion", 1) || !exactInteger("width", width) ||
85 !exactInteger("height", height) || !exactInteger("depth", depth) ||
86 !exactString("schema", "eve.volume-texture") || !exactString("encoding", "rgba8") ||
87 !exactString("usage", "noise") || !exactString("blob", "chunk:1"))
89 DiagnosticCode::ParseError, "volume definition and EVVOL bulk disagree", {}, {}, "asset.graphics.image"));
90 auto uploaded = factory_.uploadRgba8Volume(width, height, depth, std::span<const uint8_t>(bulk->bytes).subspan(24));
91 if (!uploaded) return Result<LoadedGraphicsVolumeTexture>::failure(uploaded.status());
93 {volume, uploaded.value(), std::move(payload).takeValue().variant});
94}
95
96} // namespace eve::asset_graphics
double value
Value::Object payload
double volume
std::string variant
Transactional EVIMG runtime texture loading.
std::uint32_t key
vk::UniqueImage image
std::uint32_t height
std::uint32_t width
size_t offset
std::uint64_t bytes
bool found
JSON-free versioned runtime metadata codec.
Json object
std::uint32_t depth
const AssetImportLimits & limits
Stable asset identity backed by PersistentId.
Definition ResourceRef.h:53
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
std::map< std::string, Value > Object
Definition Value.h:34
Result< RuntimeAssetPayload > read(const AssetRef &asset, std::string_view expectedType, const EvpackCapabilities &capabilities, std::uint64_t maximumDecodedBytes) const
Resolve, type-check, variant-select and decode a canonical runtime asset.
Result< LoadedGraphicsImage > load(const AssetRef &image, const asset::EvpackCapabilities &capabilities, const ImageAssetLoadLimits &limits={}) const
Validate and upload image/3 mip assets, retaining image/2 single-level compatibility.
Result< LoadedGraphicsVolumeTexture > load(const AssetRef &volume, const asset::EvpackCapabilities &capabilities, const VolumeTextureAssetLoadLimits &limits={}) const
Validate definition and EVVOL bulk before atomically uploading one volume.
virtual Result< Texture * > uploadRgba8MipChain(uint32_t width, uint32_t height, uint32_t levels, std::span< const uint8_t > pixels)
Upload complete explicit linear RGBA8 mips without regeneration.
virtual Result< Texture * > uploadRgba8Volume(uint32_t width, uint32_t height, uint32_t depth, std::span< const uint8_t > pixels)
Upload one tightly packed linear RGBA8 volume.
virtual Result< Texture * > uploadRgba8(std::uint32_t width, std::uint32_t height, const std::uint8_t *pixels, bool srgb)=0
Upload one tightly packed, top-down RGBA8 image.
std::uint32_t little32(std::span< const std::uint8_t > bytes, std::size_t offset)
Read a uint32 after the caller has bounded the byte range.
Result< Value > decodeRuntimeDefinition(std::span< const std::uint8_t > bytes, const RuntimeDefinitionLimits &limits)
Decode a bounded EVDEF\0\1 metadata tree without a JSON parser.
Result< DecodedEvpackImage > decodeEvpackImage(const EvpackResourceReader &reader, const AssetRef &image, const EvpackCapabilities &capabilities, const EvpackImageDecodeLimits &limits)
Decode and validate canonical eve.image/3 data with eve.image/2 compatibility.
Actual runtime device capabilities used for variant selection.
Definition Evpack.h:92
Bounds applied before allocating decoded image bytes.
One decoded runtime chunk with its admitted semantic metadata.
std::vector< std::uint8_t > bytes
Bounds checked before backend volume allocation.