载入中...
搜索中...
未找到
AssetCooker.cpp
浏览该文件的文档.
1#include "asset/AssetCooker.h"
6#include "asset/ShaderAsset.h"
7
10
11#include "data/HashFunction.h"
12
13#include <algorithm>
14#include <map>
15#include <set>
16
17namespace eve::asset {
18namespace {
19
20std::array<std::uint8_t, 32> sha256(std::span<const std::uint8_t> bytes) {
23 ->hash("sha256", reinterpret_cast<const char*>(bytes.data()), bytes.size(), digest);
24 std::array<std::uint8_t, 32> result{};
25 std::copy_n(reinterpret_cast<const std::uint8_t*>(digest.data), result.size(), result.begin());
26 return result;
27}
28
29void appendString(std::vector<std::uint8_t>& bytes, std::string_view text) {
30 const std::uint64_t size = text.size();
31 for (unsigned shift = 0; shift != 64; shift += 8) bytes.push_back(static_cast<std::uint8_t>(size >> shift));
32 bytes.insert(bytes.end(), text.begin(), text.end());
33}
34
35PersistentId buildIdentity(const EvaArchive& source, const AssetCookProfile& profile,
36 std::string_view canonicalManifest) {
37 std::vector<std::uint8_t> key;
38 appendString(key, "eve.asset-cooker/1");
39 appendString(key, evpackCodecBuildIdentity(profile.chunkCodec));
40 const auto packageBytes = source.manifest.packageId.bytes();
41 key.insert(key.end(), packageBytes.begin(), packageBytes.end());
42 appendString(key, canonicalManifest);
43 appendString(key, profile.variant.os); appendString(key, profile.variant.arch);
44 appendString(key, profile.variant.graphics); appendString(key, profile.variant.shaderFormat);
45 appendString(key, profile.variant.quality);
46 for (const auto& family : profile.variant.textureFamilies) appendString(key, family);
47 for (const auto& feature : profile.variant.features) appendString(key, feature);
48 for (unsigned shift = 0; shift != 32; shift += 8)
49 key.push_back(static_cast<std::uint8_t>(profile.bulkAlignment >> shift));
50 for (const auto& entry : source.entries) {
51 appendString(key, entry.path);
52 const auto hash = sha256(entry.bytes);
53 key.insert(key.end(), hash.begin(), hash.end());
54 }
55 auto digest = sha256(key);
57 std::copy_n(digest.begin(), bytes.size(), bytes.begin());
58 bytes[6] = static_cast<std::uint8_t>((bytes[6] & 0x0f) | 0x50);
59 bytes[8] = static_cast<std::uint8_t>((bytes[8] & 0x3f) | 0x80);
60 return PersistentId(bytes);
61}
62
63const Value* field(const Value::Object& object, std::string_view name) {
64 const auto found = object.find(std::string(name));
65 return found == object.end() ? nullptr : &found->second;
66}
67
68bool predicateText(const Value::Object& predicate, std::string_view name, std::string_view actual) {
69 const Value* value = field(predicate, name);
70 return !value || (value->isString() && value->asString() == actual);
71}
72
73bool platformDependencyApplies(const EvaDependency& dependency, const EvpackVariant& variant) {
74 if (dependency.kind != EvaDependencyKind::Platform) return true;
75 return predicateText(dependency.predicate, "os", variant.os) &&
76 predicateText(dependency.predicate, "arch", variant.arch) &&
77 predicateText(dependency.predicate, "graphics", variant.graphics) &&
78 predicateText(dependency.predicate, "quality", variant.quality);
79}
80
81Result<void> validatePublication(const EvaManifest& manifest, CookPublication publication) {
83 const Value* license = field(manifest.provenance, "license");
84 const auto* object = license ? license->getIf<Value::Object>() : nullptr;
85 const Value* redistribution = object ? field(*object, "redistribution") : nullptr;
86 if (!redistribution || !redistribution->isString() ||
87 (redistribution->asString() != "runtime-embedded" && redistribution->asString() != "project-only"))
90 "public Cook requires an explicit redistribution policy", "$.provenance.license.redistribution", {},
91 "asset.cook"));
92 return Result<void>::success();
93}
94
95EvpackChunkKind kindForPath(std::string_view path) {
96 if (path.find("/stream/") != std::string_view::npos) return EvpackChunkKind::Stream;
97 if (path.find("/shaders/") != std::string_view::npos) return EvpackChunkKind::Shader;
99}
100
101Result<std::vector<std::uint8_t>> binaryDefinition(
102 std::span<const std::uint8_t> json, std::uint64_t maximumBytes,
103 std::span<const EvaDependency> dependencies = {}) {
104 auto parsed = Value::fromJson(std::string_view(
105 reinterpret_cast<const char*>(json.data()), json.size()));
106 if (!parsed) return Result<std::vector<std::uint8_t>>::failure(parsed.status());
107 auto* object = parsed.value().getIf<Value::Object>();
108 if (!object)
110 DiagnosticCode::ParseError, "runtime definition root must be an object", {}, {}, "asset.cook"));
111 Value::Array fallbacks;
112 for (const auto& dependency : dependencies) {
113 if (dependency.kind != EvaDependencyKind::RuntimeOptional) continue;
114 Value::Object fallback;
115 fallback["path"] = Value(dependency.path);
116 fallback["to"] = Value(dependency.to.format());
117 fallback["expectedType"] = Value(dependency.expectedType);
118 fallback["policy"] = Value(dependency.fallback);
119 fallbacks.emplace_back(std::move(fallback));
120 }
121 if (!fallbacks.empty()) (*object)["dependencyFallbacks"] = Value(std::move(fallbacks));
123 limits.maximumBytes = maximumBytes;
124 return encodeRuntimeDefinition(parsed.value(), limits);
125}
126
127} // namespace
128
130 AssetCookProfile profile;
132 if (target == "windows-x86_64-vulkan")
133 profile.variant = {"windows", "x86_64", "vulkan", {"bc", "rgba8"}, "spirv-1.6", "high", {}};
134 else if (target == "linux-x86_64-vulkan")
135 profile.variant = {"linux", "x86_64", "vulkan", {"bc", "rgba8"}, "spirv-1.6", "high", {}};
136 else if (target == "macos-arm64-vulkan")
137 profile.variant = {"macos", "arm64", "vulkan", {"rgba8"}, "spirv-1.6", "high", {}};
138 else if (target == "android-arm64-vulkan")
139 profile.variant = {"android", "arm64", "vulkan", {"astc", "etc2", "rgba8"}, "spirv-1.6", "high", {}};
140 else if (target == "ios-arm64-vulkan")
141 profile.variant = {"ios", "arm64", "vulkan", {"astc", "rgba8"}, "spirv-1.6", "high", {}};
142 else if (target == "web-wasm32-webgpu")
143 profile.variant = {"web", "wasm32", "webgpu", {"rgba8"}, "wgsl-1", "high", {}};
144 else
146 DiagnosticCode::Unsupported, "unknown asset Cook target", std::string(target), {}, "asset.cook"));
147 return Result<AssetCookProfile>::success(std::move(profile));
148}
149
151 const EvaArchiveLimits& evaLimits,
152 const EvpackLimits& evpackLimits) {
153 auto migrated = migrateEvaArchive(source, evaLimits);
154 if (!migrated) return Result<AssetCookReceipt>::failure(migrated.status());
155 auto rebuilt = buildEvaArchive(migrated.value().manifest, migrated.value().entries, evaLimits);
156 if (!rebuilt) return Result<AssetCookReceipt>::failure(rebuilt.status());
157 auto admitted = parseEvaArchive(rebuilt.value(), evaLimits);
158 if (!admitted) return Result<AssetCookReceipt>::failure(admitted.status());
159 EvaArchive canonical = std::move(admitted).takeValue();
160 EvaManifest dependencyManifest = canonical.manifest;
161 std::erase_if(dependencyManifest.dependencies, [&](const EvaDependency& dependency) {
162 return dependency.kind == EvaDependencyKind::Platform &&
163 !platformDependencyApplies(dependency, profile.variant);
164 });
165 auto dependencyValidation = validateEvaDependencies(dependencyManifest,
166 profile.availableDependencies);
167 if (!dependencyValidation)
168 return Result<AssetCookReceipt>::failure(dependencyValidation.status());
169 auto canonicalManifest = serializeEvaManifest(canonical.manifest);
170 if (!canonicalManifest) return Result<AssetCookReceipt>::failure(canonicalManifest.status());
171 auto publication = validatePublication(canonical.manifest, profile.publication);
172 if (!publication) return Result<AssetCookReceipt>::failure(publication.status());
173
174 std::map<PersistentId, std::vector<PersistentId>> runtimeDependencies;
175 for (const auto& dependency : canonical.manifest.dependencies) {
176 if (dependency.kind == EvaDependencyKind::RuntimeOptional ||
177 dependency.kind == EvaDependencyKind::Build || dependency.kind == EvaDependencyKind::Editor ||
178 dependency.kind == EvaDependencyKind::Source || !platformDependencyApplies(dependency, profile.variant))
179 continue;
180 const bool present = std::binary_search(dependencyValidation.value().presentAssets.begin(),
181 dependencyValidation.value().presentAssets.end(),
182 dependency.to.id());
183 if (present) runtimeDependencies[dependency.from.id()].push_back(dependency.to.id());
184 }
185 for (auto& [asset, dependencies] : runtimeDependencies) {
186 (void)asset;
187 std::sort(dependencies.begin(), dependencies.end());
188 dependencies.erase(std::unique(dependencies.begin(), dependencies.end()), dependencies.end());
189 }
190
191 EvpackBuild build;
192 build.packageId = canonical.manifest.packageId;
193 build.buildId = buildIdentity(canonical, profile, canonicalManifest.value());
194 build.variants.push_back(profile.variant);
195 for (const auto& asset : canonical.manifest.assets) {
196 std::vector<EvaDependency> assetDependencyPolicies;
197 for (const auto& dependency : canonical.manifest.dependencies)
198 if (dependency.from.id() == asset.asset.id() &&
199 platformDependencyApplies(dependency, profile.variant))
200 assetDependencyPolicies.push_back(dependency);
201 const auto definition = std::lower_bound(canonical.entries.begin(), canonical.entries.end(), asset.definition,
202 [](const EvaArchiveEntry& entry, std::string_view path) {
203 return entry.path < path;
204 });
205 if (definition == canonical.entries.end() || definition->path != asset.definition)
207 DiagnosticCode::NotFound, "asset definition is missing", asset.definition, {}, "asset.cook"));
208 const auto dependencies = runtimeDependencies[asset.asset.id()];
209 if (asset.type == "eve.shader") {
210 if (profile.variant.graphics != "vulkan" || profile.variant.shaderFormat != "spirv-1.6")
212 Diagnostic::error(DiagnosticCode::Unsupported, "eve.shader/1 requires Vulkan SPIR-V 1.6 target",
213 asset.definition, {}, "asset.cook"));
214 auto value = Value::fromJson(
215 std::string_view(reinterpret_cast<const char*>(definition->bytes.data()), definition->bytes.size()));
216 if (!value) return Result<AssetCookReceipt>::failure(value.status());
217 auto shader = decodeShaderAsset(value.value());
218 if (!shader) return Result<AssetCookReceipt>::failure(shader.status());
219 const std::string shaderPrefix = "assets/" + asset.asset.id().format() + "/";
220 if (!assetDependencyPolicies.empty() ||
221 std::any_of(canonical.entries.begin(), canonical.entries.end(), [&](const EvaArchiveEntry& entry) {
222 return entry.path.starts_with(shaderPrefix) && entry.path != asset.definition;
223 }))
225 "eve.shader/1 must be self-contained",
226 asset.definition, {}, "asset.cook"));
227 }
228 if (asset.type == "eve.image") {
229 if (std::find(profile.variant.textureFamilies.begin(),
230 profile.variant.textureFamilies.end(), "rgba8") ==
231 profile.variant.textureFamilies.end())
233 DiagnosticCode::Unsupported, "eve.image/3 requires an explicit rgba8 target texture family",
234 asset.definition, {}, "asset.cook"));
235 auto parsedDefinition = Value::fromJson(std::string_view(
236 reinterpret_cast<const char*>(definition->bytes.data()), definition->bytes.size()));
237 if (!parsedDefinition)
238 return Result<AssetCookReceipt>::failure(parsedDefinition.status());
239 const auto* definitionObject = parsedDefinition.value().getIf<Value::Object>();
240 const Value* blobValue = definitionObject ? field(*definitionObject, "blob") : nullptr;
241 if (!blobValue || !blobValue->isString())
243 "eve.image/3 source blob path is missing",
244 asset.definition, {}, "asset.cook"));
245 const auto sourceBlob = std::lower_bound(
246 canonical.entries.begin(), canonical.entries.end(), blobValue->asString(),
247 [](const EvaArchiveEntry& entry, std::string_view path) { return entry.path < path; });
248 if (sourceBlob == canonical.entries.end() || sourceBlob->path != blobValue->asString())
250 "eve.image/3 source blob is missing",
251 blobValue->asString(), {}, "asset.cook"));
252 auto image = cookCanonicalImageRgba8(definition->bytes, sourceBlob->bytes,
253 evpackLimits.maximumChunkBytes);
254 if (!image) return Result<AssetCookReceipt>::failure(image.status());
255 auto runtimeDefinition = binaryDefinition(image.value().definition,
256 evpackLimits.maximumChunkBytes,
257 assetDependencyPolicies);
258 if (!runtimeDefinition)
259 return Result<AssetCookReceipt>::failure(runtimeDefinition.status());
260 build.chunks.push_back({asset.asset.id(), asset.type, asset.schemaVersion, 0,
262 dependencies, std::move(runtimeDefinition).takeValue()});
263 build.chunks.push_back({asset.asset.id(), asset.type, asset.schemaVersion, 0,
265 profile.bulkAlignment, dependencies,
266 std::move(image).takeValue().bulk});
267 continue;
268 }
269 if (asset.type == "eve.volume-texture") {
270 if (std::find(profile.variant.textureFamilies.begin(), profile.variant.textureFamilies.end(), "rgba8") ==
271 profile.variant.textureFamilies.end())
274 "eve.volume-texture/1 requires an explicit rgba8 target texture family",
275 asset.definition, {}, "asset.cook"));
276 auto parsedDefinition = Value::fromJson(
277 std::string_view(reinterpret_cast<const char*>(definition->bytes.data()), definition->bytes.size()));
278 if (!parsedDefinition) return Result<AssetCookReceipt>::failure(parsedDefinition.status());
279 const auto* definitionObject = parsedDefinition.value().getIf<Value::Object>();
280 const Value* blobValue = definitionObject ? field(*definitionObject, "blob") : nullptr;
281 if (!blobValue || !blobValue->isString())
283 Diagnostic::error(DiagnosticCode::ParseError, "eve.volume-texture/1 source blob path is missing",
284 asset.definition, {}, "asset.cook"));
285 const auto sourceBlob =
286 std::lower_bound(canonical.entries.begin(), canonical.entries.end(), blobValue->asString(),
287 [](const EvaArchiveEntry& entry, std::string_view path) { return entry.path < path; });
288 if (sourceBlob == canonical.entries.end() || sourceBlob->path != blobValue->asString())
290 Diagnostic::error(DiagnosticCode::NotFound, "eve.volume-texture/1 source blob is missing",
291 blobValue->asString(), {}, "asset.cook"));
292 auto volume =
293 cookCanonicalVolumeTextureRgba8(definition->bytes, sourceBlob->bytes, evpackLimits.maximumChunkBytes);
294 if (!volume) return Result<AssetCookReceipt>::failure(volume.status());
295 auto runtimeDefinition =
296 binaryDefinition(volume.value().definition, evpackLimits.maximumChunkBytes, assetDependencyPolicies);
297 if (!runtimeDefinition) return Result<AssetCookReceipt>::failure(runtimeDefinition.status());
298 build.chunks.push_back({asset.asset.id(), asset.type, asset.schemaVersion, 0, EvpackChunkKind::Definition,
299 0, profile.chunkCodec, 8, dependencies, std::move(runtimeDefinition).takeValue()});
300 build.chunks.push_back({asset.asset.id(), asset.type, asset.schemaVersion, 0, EvpackChunkKind::Bulk, 1,
301 EvpackCodec::None, profile.bulkAlignment, dependencies,
302 std::move(volume).takeValue().bulk});
303 continue;
304 }
305 if (asset.type == "eve.pcg-graph") {
306 auto pcg = cookCanonicalPcgGraph(definition->bytes, 4096,
307 evpackLimits.maximumChunkBytes);
308 if (!pcg) return Result<AssetCookReceipt>::failure(pcg.status());
309 auto runtimeDefinition = binaryDefinition(pcg.value().definition,
310 evpackLimits.maximumChunkBytes,
311 assetDependencyPolicies);
312 if (!runtimeDefinition)
313 return Result<AssetCookReceipt>::failure(runtimeDefinition.status());
314 build.chunks.push_back({asset.asset.id(), asset.type, asset.schemaVersion, 0,
316 dependencies, std::move(runtimeDefinition).takeValue()});
317 build.chunks.push_back({asset.asset.id(), asset.type, asset.schemaVersion, 0,
319 profile.bulkAlignment, dependencies,
320 std::move(pcg).takeValue().executionPlan});
321 continue;
322 }
323 auto runtimeDefinition = binaryDefinition(definition->bytes,
324 evpackLimits.maximumChunkBytes,
325 assetDependencyPolicies);
326 if (!runtimeDefinition)
327 return Result<AssetCookReceipt>::failure(runtimeDefinition.status());
328 build.chunks.push_back({asset.asset.id(), asset.type, asset.schemaVersion, 0,
330 dependencies, std::move(runtimeDefinition).takeValue()});
331 const std::string prefix = "assets/" + asset.asset.id().format() + "/";
332 std::uint32_t chunkId = 1;
333 for (const auto& entry : canonical.entries) {
334 if (entry.path == asset.definition || !entry.path.starts_with(prefix)) continue;
335 build.chunks.push_back({asset.asset.id(), asset.type, asset.schemaVersion, 0,
336 kindForPath(entry.path), chunkId++, profile.chunkCodec,
337 profile.bulkAlignment, dependencies, entry.bytes});
338 }
339 }
340 const std::uint32_t chunkCount = static_cast<std::uint32_t>(build.chunks.size());
341 const PersistentId buildId = build.buildId;
342 auto packageBytes = buildEvpack(std::move(build), evpackLimits);
343 if (!packageBytes) return Result<AssetCookReceipt>::failure(packageBytes.status());
344 auto verified = parseEvpack(packageBytes.value(), evpackLimits);
345 if (!verified) return Result<AssetCookReceipt>::failure(verified.status());
347 {canonical.manifest.packageId, buildId, chunkCount, std::move(packageBytes).takeValue()});
348}
349
350} // namespace eve::asset
LogicalId target
double value
Deterministic canonical .eva to capability-targeted .evpack Cook.
Transactional migrations for canonical definitions stored in .eva.
double volume
std::string variant
Safe source-image conversion to runtime EVIMG payloads.
Canonical PCG graph compilation to runtime execution plans.
Bounded R8 volume conversion to runtime EVVOL.
Bounded deterministic compression used by the .evpack wire format.
std::array< std::uint8_t, 32 > hash
Definition Evpack.cpp:172
std::uint32_t key
vk::UniqueImage image
std::string text
std::uint64_t bytes
std::string name
std::string path
Definition PlayHost.cpp:110
Shader * shader
bool found
JSON-free versioned runtime metadata codec.
std::string digest
float size
Definition TreeMesh.cpp:156
const UnitySourceAsset & source
const AssetImportLimits & limits
const PersistentId & id() const noexcept
Return the stable asset identity.
Definition ResourceRef.h:65
std::string format() const
Return canonical asset://<uuid> text.
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
The canonical owning dynamic value used by data-facing protocols.
Definition Value.h:31
const std::string & asString() const
Return the string payload; the caller must have checked the kind.
Definition Value.cpp:87
static Result< Value > fromJson(std::string_view json)
Parse one strict JSON value into an owning Value.
Definition Value.cpp:57
std::map< std::string, Value > Object
Definition Value.h:34
bool isString() const noexcept
Return true when this value is a string.
Definition Value.h:95
std::vector< Value > Array
Definition Value.h:33
const T * getIf() const noexcept
Return a typed pointer, or nullptr when the kind differs.
Definition Value.h:180
static HashFunction * getHashFunction(std::string function)
Get a HashFunction instance for the given function.
virtual void hash(std::string function, const char *input, uint64_t length, Value &output) const =0
Hash the input, producing an set of bytes as output.
Id128 public API.
Definition Identity.h:112
std::array< std::uint8_t, 16 > Bytes
Definition Identity.h:114
Result< Evpack > parseEvpack(std::span< const std::uint8_t > bytes, const EvpackLimits &limits, const EvpackTrust &trust)
Parse, bound-check and hash-verify a complete untrusted .evpack.
Definition Evpack.cpp:542
Result< CookedCanonicalVolumeTexture > cookCanonicalVolumeTextureRgba8(std::span< const uint8_t > definition, std::span< const uint8_t > sourceR8, uint64_t maximumDecodedBytes)
Result< std::vector< std::uint8_t > > buildEvaArchive(const EvaManifest &manifest, std::vector< EvaArchiveEntry > entries, const EvaArchiveLimits &limits)
Build a deterministic ZIP64 .eva, selecting raw Deflate only when smaller than Store.
std::string evpackCodecBuildIdentity(EvpackCodec codec)
Stable codec implementation identity included in deterministic Cook keys.
Result< std::vector< std::uint8_t > > buildEvpack(EvpackBuild build, const EvpackLimits &limits)
Build deterministic little-endian .evpack bytes from validated Cook output.
Definition Evpack.cpp:248
Result< CookedCanonicalImage > cookCanonicalImageRgba8(std::span< const std::uint8_t > definition, std::span< const std::uint8_t > encodedSource, std::uint64_t maximumDecodedBytes)
Decode image/2 base images or image/3 explicit linear RGBA8 mip chains into bounded EVIMG.
Result< EvaArchive > parseEvaArchive(std::span< const std::uint8_t > bytes, const EvaArchiveLimits &limits)
Parse and fully verify an untrusted .eva ZIP64 image.
CookPublication
Publication policy controls license admission without making legal inferences.
Definition AssetCooker.h:17
Result< AssetCookReceipt > cookEvaToEvpack(const EvaArchive &source, const AssetCookProfile &profile, const EvaArchiveLimits &evaLimits, const EvpackLimits &evpackLimits)
Cook an admitted source archive into one target-specific runtime pack.
Result< EvaArchive > migrateEvaArchive(EvaArchive source, const EvaArchiveLimits &limits)
Migrate every definition in an owning archive to its current schema.
Result< CookedCanonicalPcgGraph > cookCanonicalPcgGraph(std::span< const std::uint8_t > definition, std::uint32_t maximumRules, std::uint64_t maximumPlanBytes)
Compile eve.pcg-graph/1 terrain scatter rules to a bounded PointGraph plan.
Result< AssetCookProfile > assetCookProfileForTarget(std::string_view target)
Resolve a stable CLI/tool target name to its exact capability profile.
Result< std::vector< std::uint8_t > > encodeRuntimeDefinition(const Value &value, const RuntimeDefinitionLimits &limits)
Encode an owning metadata tree as deterministic EVDEF\0\1 bytes.
Result< std::string > serializeEvaManifest(const EvaManifest &manifest)
Serialize a validated manifest as deterministic compact JSON.
Result< ShaderAsset > decodeShaderAsset(const Value &definition, const ShaderAssetLimits &limits)
Decode strict eve.shader/1 metadata with SPIR-V 1.0 through 1.6 stages.
Result< EvaDependencyValidation > validateEvaDependencies(const EvaManifest &manifest, std::span< const AvailableAssetDependency > available)
Validate local/external references, expected types and required-edge acyclicity.
EvpackChunkKind
Semantic role of a runtime chunk.
Definition Evpack.h:26
StrongUuid< detail::PersistentIdTag > PersistentId
Stable instance identity for persistence, networking and process boundaries.
Definition Identity.h:254
Explicit deterministic target profile for one runtime variant.
Definition AssetCooker.h:23
std::vector< AvailableAssetDependency > availableDependencies
Definition AssetCooker.h:28
CookPublication publication
Definition AssetCooker.h:25
One owning regular-file entry inside an .eva archive.
Definition EvaArchive.h:31
std::vector< std::uint8_t > bytes
Definition EvaArchive.h:33
Admission budgets applied before allocating decoded archive entries.
Definition EvaArchive.h:21
Fully admitted source archive with its typed manifest and payloads.
Definition EvaArchive.h:37
std::vector< EvaArchiveEntry > entries
Definition EvaArchive.h:39
One directed dependency between stable asset identities.
Definition EvaManifest.h:44
Value::Object fallback
Required observable behavior when a runtime-optional target is unavailable.
Definition EvaManifest.h:52
EvaDependencyKind kind
Definition EvaManifest.h:47
Validated, owning .eva manifest.
Definition EvaManifest.h:62
std::vector< EvaAssetEntry > assets
Definition EvaManifest.h:69
std::vector< EvaDependency > dependencies
Definition EvaManifest.h:70
Value::Object provenance
Definition EvaManifest.h:72
Complete input to deterministic .evpack assembly.
Definition Evpack.h:117
std::vector< EvpackVariant > variants
Definition Evpack.h:120
PersistentId packageId
Definition Evpack.h:118
PersistentId buildId
Definition Evpack.h:119
std::vector< EvpackChunkInput > chunks
Definition Evpack.h:121
Resource limits checked before package allocations and hash work.
Definition Evpack.h:126
std::uint64_t maximumChunkBytes
Definition Evpack.h:128
Capability-addressed runtime representation; list order is fallback order.
Definition Evpack.h:81
std::string quality
Definition Evpack.h:87
std::string shaderFormat
Definition Evpack.h:86
std::vector< std::string > features
Definition Evpack.h:88
std::vector< std::string > textureFamilies
Definition Evpack.h:85
std::string graphics
Definition Evpack.h:84
Structural and allocation limits for untrusted EVDEF metadata.