Skip to content

[Renderer] Add capability-tiered global material and texture indirection #130

Description

@proggeramlug

Parent: #126
Related: #27, #28

Problem

GPU-driven draws and visibility-buffer shading require geometry/material resources to be addressable from GPU-visible IDs. Bloom still relies heavily on per-material/per-draw binding, while wgpu feature support differs across Metal, DX12, Vulkan, mobile, and WebGPU. Making “bindless” mandatory would break the engine's broad platform promise; avoiding indirection blocks modern rendering architecture.

Outcome

One generation-safe resource-ID model with capability-tiered implementations:

  • Tier A: descriptor-indexed/global texture and sampler tables where the adapter/backend supports the required features robustly;
  • Tier B: paged texture arrays/atlases plus material indirection with bounded page switches;
  • Tier C: existing bind-group material path as a correctness fallback.

Shaders and scene data consume stable IDs; only the backend table implementation varies.

Architecture contract

IDs and lifetime

  • Separate typed IDs for material, texture, sampler, mesh, and buffer views.
  • IDs contain or reference a generation so stale handles resolve to a diagnostic fallback, never an unrelated reused resource.
  • A residency manager owns allocation, retirement after GPU completion, fallback resources, and per-frame update batches.
  • Define hard limits and expose them through renderer capabilities.

Material data

  • Move scalar/vector PBR parameters into a GPU storage buffer indexed by material_id.
  • Store texture/sampler IDs in the material record; do not embed backend bind-group objects in scene/material ownership.
  • Keep the existing custom-material ABI functional. Version the ABI only if unavoidable and provide migration diagnostics.

Capability selection

  • Probe actual adapter features/limits at device creation; do not infer solely from OS/backend.
  • Tier selection is logged and queryable from TypeScript.
  • Allow a test/debug override to force each lower tier on capable hardware.
  • Web/mobile limits must be derived from adapter.limits(), not desktop defaults.

Shader interface

  • Centralize resource lookup helpers in shared WGSL.
  • Out-of-range/nonresident IDs sample visible diagnostic defaults in debug and safe neutral defaults in release.
  • Preserve correct color-space and normal-map sampling across table implementations.

Staged implementation

  1. Introduce IDs, GPU material records, and Tier C adapter without changing draw behavior.
  2. Implement Tier B using texture-array pages; group indirect draws by page when necessary.
  3. Implement Tier A only behind explicit feature checks and backend tests.
  4. Switch perf ticket 009: GPU-driven rendering — indirect multi-draw + GPU cull #28 and perf ticket 008: visibility buffer (Nanite-style) replaces 4-MRT G-buffer #27 to consume the common IDs.
  5. Add streaming residency hooks without implementing the full cooker/streamer here.

Acceptance criteria

  • A stress scene with at least 4,096 material textures and 10,000 visible material instances renders without handle corruption; tier-specific documented limits may reduce resident textures but must stream/fallback deterministically.
  • Tier A performs no per-material bind-group creation or switching inside the opaque GPU-driven pass.
  • Tier B reports page count/switches and stays within documented adapter limits.
  • Forced Tier C matches current rendering and keeps web/mobile adapters functional.
  • Destroy/recreate/churn tests prove stale IDs cannot alias newly allocated resources.
  • sRGB, linear data, HDR, normal, mip, and sampler modes have golden coverage.
  • The quality corpus matches the existing material path within tolerance before perf ticket 008: visibility buffer (Nanite-style) replaces 4-MRT G-buffer #27 migration.
  • TypeScript exposes a read-only capability/limit report and receives an actionable error when a requested resource class is unsupported.

Likely files

  • native/shared/src/renderer/material_system.rs
  • native/shared/src/renderer/material_pipeline.rs
  • native/shared/src/renderer/material_system_wasm.rs
  • native/shared/src/renderer/shaders/
  • native/shared/shaders/material_abi.wgsl
  • native/shared/src/handles.rs
  • device creation in native/*/src/lib.rs
  • public capability API under src/core/ or src/models/

Non-goals

  • Requiring descriptor indexing on all platforms.
  • Virtual texture page streaming itself.
  • Removing the compatibility renderer before every target passes.

Dependencies

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions