Backend diet series, manifest items 1+3 (scratch/metal_backend_diet_manifest.md):
- GetOrCreateEdramLoadLibrary/GetOrCreateEdramLoadPipeline and their header
declarations, member maps, and cleanup-only drains: the embedded
edram_load_vs/ps MSL pipeline had no draw or resolve path caller anywhere
in src/ (the hazard design doc had already flagged it dead; caveat
updated to 'removed'). 302 lines.
- The telemetry-only re-derivation of the texture upload-compatibility
classification in the texture cache (the third redundant computation of
the route classification): its only outputs fed
RecordTextureUploadCompatibility/ComputeBlocker; the real upload
decisions (use_blit_upload/direct_uploads/repack) are computed elsewhere
and untouched. The texture_upload_classification telemetry line now
prints zeros; the recorders and their print plumbing stay for now (their
removal is bundled with live telemetry formatting and belongs to the
telemetry-extraction commit). 62 lines.
366 deletions, no behavior change on any draw/upload path.
Wires the previously-unconsumed metal_backend_hazard_model cvars per
docs/metal_hazard_model_design.md and Apple's Game Porting Toolkit 4
synchronization guidance (producer stage = previous usage, consumer
stage = new usage; MTLFence orders encoders across command buffers on
one queue, so the standalone-command-buffer edges are fence-coverable
and events stay unnecessary on a single queue).
With metal_backend_hazard_model set, the shared-memory buffer is
created HazardTrackingModeUntracked - removing the driver's per-encoder
dependency analysis for the hottest buffer in the backend - and
ordering comes from explicit edges:
- Upload blit encoders update the shared-memory fence at end when they
encoded copies (Blit producer); render encoders wait on creation
before the Vertex/Object/Mesh stages (vertex+index fetch consumers),
texture-cache untile compute encoders wait on creation (guest-source
reads), and blit read dependencies wait unconditionally.
- The memexport DMA index copy splits the shared upload encoder when it
already holds copies, since untracked buffers have no intra-encoder
write-to-read ordering in a blit encoder.
- Direct host resolve dispatches wait before and update after their
unscaled shared-memory destination writes (Dispatch producer).
- Memexport render writes keep their existing unconditional fence
update at encoder end.
metal_backend_hazard_model_validate emits the same edges while driver
tracking stays on, for per-title soak testing with zero behavior
change; both modes report edge counts on the telemetry hazard_model
line. The residency-set side of the model (queue-resident shared
memory/EDRAM/bindless heaps/texture pool heaps with covered-resource
useResource/useHeap skips) already exists and is documented as such.
https://claude.ai/code/session_01H7PSbmf3he3m3kEcBEcJ4V
The native MSL path is the permanent renderer (MSC remains as the
correctness-parity baseline), so it gets the same treatment the MSC
helper pipelines just received:
- Native mesh (point/rect/quad list) and native tessellation pipelines
are now created on the pipeline creation threads from inputs captured
in the cache placeholder, including the EnsureNativeMslTranslationReady
calls that previously ran the full translate+metallib compile on the
draw thread per first use. Draws skip silently while pending and only
log on genuine failure. NativeMeshPipelineState publishes through an
atomic pipeline pointer like the other helper states; native and MSC
tessellation share the request type and dispatch on the native_msl
flag.
- Native MSL translation no longer serializes every creation thread on
one global mutex around the single shared MslShaderTranslator:
translation uses per-thread translators and disassembly scratch under
the same per-shader striped locks as the DXBC path, and the
install/compile step is covered by the stripe so the same translation
is never built twice in parallel. The now-unused global
shader_translation_mutex_ is removed.
- The command processor's draw-thread ucode analysis goes through a
stripe-locked AnalyzeShaderUcode helper so it cannot race prewarm
creation threads analyzing the same shader with the shared scratch
buffer.
Safe to defer per draw because ConfigureNativeMslVariant is write-once:
the texture-sign variant is frozen on the translation before the getter
runs, so background translation cannot pick up a different variant.
Also relocate the hazard model design doc to docs/ (scratch/ is
gitignored) and point the metal_backend_hazard_model cvar text at it.
The doc records what is already implemented (heap-collapsed residency,
serial-gated batched useResource), the complete shared-memory buffer
consumer inventory with required fence edges, and the shadow-validated
rollout the cvars exist for.
https://claude.ai/code/session_01H7PSbmf3he3m3kEcBEcJ4V