Implementation
static TraceEvent fromJson(
Map<String, Object?> j,
TraceBlobReader blob,
) => switch (j['kind']) {
'beginFrame' => const TraceBeginFrame(),
'uploadGeometry' => TraceUploadGeometry(
id: asInt(j['id']),
usage: usageFromJson(j['usage']),
bytes: blob.read(j['bytes']),
),
'overwriteGeometry' => TraceOverwriteGeometry(
target: _range(j['target']),
offset: asInt(j['offset']),
bytes: blob.read(j['bytes']),
),
'releaseGeometry' => TraceReleaseGeometry(asInt(j['buffer'])),
'createTexture' => TraceCreateTexture(
id: asInt(j['id']),
spec: specFromJson(j['spec']),
),
'createTextureFromPixels' => TraceCreateTextureFromPixels(
id: asInt(j['id']),
width: asInt(j['width']),
height: asInt(j['height']),
format: byName(TextureFormat.values, j['format']),
pixels: blob.read(j['pixels']),
mipLevels: (j['mipLevels'] as List<Object?>?)?.map(blob.read).toList(),
),
'createCubeTextureFromPixels' => TraceCreateCubeTextureFromPixels(
id: asInt(j['id']),
size: asInt(j['size']),
format: byName(TextureFormat.values, j['format']),
faces: (j['faces']! as List<Object?>).map(blob.read).toList(),
mipLevels: (j['mipLevels'] as List<Object?>?)
?.map((f) => (f! as List<Object?>).map(blob.read).toList())
.toList(),
),
'createCubeRenderTarget' => TraceCreateCubeRenderTarget(
id: asInt(j['id']),
size: asInt(j['size']),
format: byName(TextureFormat.values, j['format']),
mipLevels: asInt(j['mipLevels']),
),
'overwriteTexture' => TraceOverwriteTexture(
texture: asInt(j['texture']),
rgba: blob.read(j['rgba']),
region: j['region'] == null ? null : screenRectFromJson(j['region']),
mipLevel: asInt(j['mipLevel']),
),
'releaseTexture' => TraceReleaseTexture(asInt(j['texture'])),
'loadShaders' => TraceLoadShaders(blob.read(j['bytes'])),
'createPipeline' => TraceCreatePipeline(
id: asInt(j['id']),
vertex: j['vertex']! as String,
fragment: j['fragment']! as String,
layout: j['layout'] == null ? null : layoutFromJson(j['layout']),
),
'beginRenderPass' => TraceBeginRenderPass(
pass: asInt(j['pass']),
label: j['label'] as String?,
colors: <TraceColorTarget>[
for (final c in (j['colors']! as List<Object?>).map(asMap))
(
texture: asInt(c['texture']),
resolveTexture: c['resolveTexture'] == null
? null
: asInt(c['resolveTexture']),
loadAction: byName(LoadAction.values, c['loadAction']),
storeAction: byName(StoreAction.values, c['storeAction']),
clearValue: c['clearValue'] == null
? null
: vector4FromJson(c['clearValue']),
face: asInt(c['face']),
mipLevel: asInt(c['mipLevel']),
),
],
depth: switch (j['depth']) {
null => null,
final Object d => (
texture: asInt(asMap(d)['texture']),
clearValue: asDouble(asMap(d)['clearValue']),
// Absent from a trace written before `R8` let a pass load depth,
// and absent means what every pass did then.
loadAction: asMap(d)['loadAction'] == null
? LoadAction.clear
: byName(LoadAction.values, asMap(d)['loadAction']),
storeAction: asMap(d)['storeAction'] == null
? StoreAction.dontCare
: byName(StoreAction.values, asMap(d)['storeAction']),
stencilLoadAction: byName(
LoadAction.values,
asMap(d)['stencilLoadAction'],
),
stencilStoreAction: byName(
StoreAction.values,
asMap(d)['stencilStoreAction'],
),
stencilClearValue: asInt(asMap(d)['stencilClearValue']),
),
},
),
'readPixels' => TraceReadPixels(asInt(j['texture'])),
'readback' => TraceReadback(
texture: asInt(j['texture']),
region: j['region'] == null ? null : screenRectFromJson(j['region']),
),
'setViewport' => TraceSetViewport(
asInt(j['pass']),
screenRectFromJson(j['rect']),
),
'setScissor' => TraceSetScissor(
asInt(j['pass']),
screenRectFromJson(j['rect']),
),
'setPrimitiveType' => TraceSetPrimitiveType(
asInt(j['pass']),
byName(PrimitiveType.values, j['value']),
),
'setPolygonMode' => TraceSetPolygonMode(
asInt(j['pass']),
byName(PolygonMode.values, j['value']),
),
'setCullMode' => TraceSetCullMode(
asInt(j['pass']),
byName(CullMode.values, j['value']),
),
'setWindingOrder' => TraceSetWindingOrder(
asInt(j['pass']),
byName(WindingOrder.values, j['value']),
),
'setDepthWrite' => TraceSetDepthWrite(
asInt(j['pass']),
j['value']! as bool,
),
'setDepthCompare' => TraceSetDepthCompare(
asInt(j['pass']),
byName(CompareFunction.values, j['value']),
),
'setStencil' => TraceSetStencil(
asInt(j['pass']),
stencilFromJson(j['front']),
j['back'] == null ? null : stencilFromJson(j['back']),
),
'setStencilReference' => TraceSetStencilReference(
asInt(j['pass']),
asInt(j['value']),
),
'setBlend' => TraceSetBlend(
asInt(j['pass']),
j['state'] == null ? null : blendFromJson(j['state']),
asInt(j['attachment']),
),
'setBlendColor' => TraceSetBlendColor(
asInt(j['pass']),
vector4FromJson(j['color']),
),
'bindPipeline' => TraceBindPipeline(asInt(j['pass']), asInt(j['pipeline'])),
'bindVertexBuffer' => TraceBindVertexBuffer(
pass: asInt(j['pass']),
buffer: _range(j['buffer']),
vertexCount: asInt(j['vertexCount']),
slot: asInt(j['slot']),
),
'bindVertexData' => TraceBindVertexData(
pass: asInt(j['pass']),
bytes: blob.read(j['bytes']),
vertexCount: asInt(j['vertexCount']),
slot: asInt(j['slot']),
),
'bindIndexBuffer' => TraceBindIndexBuffer(
pass: asInt(j['pass']),
buffer: _range(j['buffer']),
type: byName(IndexType.values, j['type']),
indexCount: asInt(j['indexCount']),
),
'bindIndexData' => TraceBindIndexData(
pass: asInt(j['pass']),
bytes: blob.read(j['bytes']),
type: byName(IndexType.values, j['type']),
indexCount: asInt(j['indexCount']),
),
'bindUniformBlock' => TraceBindUniformBlock(
pass: asInt(j['pass']),
shader: j['shader']! as String,
block: j['block']! as String,
members: _members(j['members'], blob),
),
'bindTexture' => TraceBindTexture(
pass: asInt(j['pass']),
shader: j['shader']! as String,
slot: j['slot']! as String,
texture: asInt(j['texture']),
sampler: j['sampler'] == null ? null : samplerFromJson(j['sampler']),
),
'clearBindings' => TraceClearBindings(asInt(j['pass'])),
'draw' => TraceDraw(asInt(j['pass']), asInt(j['instanceCount'])),
'submit' => TraceSubmit(asInt(j['pass'])),
'createStorageBuffer' => TraceCreateStorageBuffer(
id: asInt(j['id']),
bytes: blob.read(j['bytes']),
hostReadable: j['hostReadable']! as bool,
),
'releaseStorageBuffer' => TraceReleaseStorageBuffer(asInt(j['buffer'])),
'createComputePipeline' => TraceCreateComputePipeline(
asInt(j['id']),
j['shader']! as String,
),
'beginComputePass' => TraceBeginComputePass(
asInt(j['pass']),
j['label'] as String?,
),
'computeBindPipeline' => TraceComputeBindPipeline(
asInt(j['pass']),
asInt(j['pipeline']),
),
'computeBindStorageBuffer' => TraceComputeBindStorageBuffer(
pass: asInt(j['pass']),
shader: j['shader']! as String,
name: j['name']! as String,
buffer: asInt(j['buffer']),
),
'computeBindUniformBlock' => TraceComputeBindUniformBlock(
pass: asInt(j['pass']),
shader: j['shader']! as String,
block: j['block']! as String,
members: _members(j['members'], blob),
),
'dispatch' => TraceDispatch(
asInt(j['pass']),
asInt(j['x']),
asInt(j['y']),
asInt(j['z']),
),
'computeSubmit' => TraceComputeSubmit(asInt(j['pass'])),
'readBuffer' => TraceReadBuffer(asInt(j['buffer'])),
final other => throw FormatException(
'a trace event of kind $other, which this build does not know',
),
};