# Renderer API Backend-Neutral Contract

## Purpose

`pp_renderer_api` defines the backend-neutral rendering contract used by `pp_paint_renderer`
and the higher-level app core. This document captures the minimum behavior that any
concrete backend (`pp_renderer_gl` today, Vulkan/Metal later) must preserve.

## Contract Scope

- Public interfaces:
  - `pp::renderer::IRenderDevice`
  - `pp::renderer::ICommandContext`
  - `pp::renderer::ITexture2D`
  - `pp::renderer::IRenderTarget`
  - `pp::renderer::IShaderProgram`
  - `pp::renderer::IMesh`
  - `pp::renderer::IReadbackBuffer`
  - `pp::renderer::IRenderTrace`
  - `pp::renderer::Recording*` helpers in `renderer_api/recording_renderer.*`
- Validation helpers in `renderer_api.h` and shader catalog helpers in
  `renderer_api/shader_catalog.*`

## Behavioral Invariants

- No exceptions are part of API control flow; failures are reported through
  `pp::foundation::Status` / `pp::foundation::Result`.
- Object lifetimes remain backend-owned; API consumers pass references/handles only.
- Resource descriptors and command/state descriptors must be validated and constrained by the
  helper functions.
- Backends may reject unsupported operations via explicit non-OK status but must not mutate
  visible program state before reporting failure.
- Error codes and debug names are deterministic and backend-neutral (human-readable and
  test-stable where feasible).

## Surface Contracts

1. `IRenderDevice`

- `backend_name()` identifies backend family.
- `features()` returns capability bits used for planner decisions.
- Resource creation methods return `Result` and report allocation/validation failures.
- `immediate_context()` is stable for the lifetime of the device object.
- `trace()` may return `nullptr`; callers must tolerate no trace provider.

2. `ICommandContext`

- State mutation (`set_viewport`, `set_scissor`, blend/depth/shader/sampler/mesh/program binds) is
  explicit and backend-agnostic.
- Command methods that can fail must return status.
- `end_render_pass()` is always side-effect safe and non-throwing.
- `read_texture` / `capture_frame` readback contracts are byte-sized and descriptor-driven.
- Texture upload/copy/readback/transition methods must respect descriptor bounds and ordering rules.

3. Resource descriptors and helpers

- `TextureDesc`, `Extent2D`, `Viewport`, `ScissorRect`, `RenderPassDesc`,
  `TextureUsage`, `TextureState`, `BlendState`, `DepthState`, sampler/topology enums
  are shared semantic vocabulary across backends.
- Validation helpers (`validate_*`) are the compatibility fence for contract behavior.
- `PaintFeedbackPlan` and `plan_paint_feedback(...)` are the feature/algorithm decision seam
  for framebuffer feedback vs ping-pong workflows.

4. Trace and recording

- `IRenderTrace` is optional and may be elided, but implementations should support scoped markers
  and markers where used.
- Recording backend (`RecordingRenderDevice`, `RecordingCommandContext`) must preserve command
  order and reject invalid sequences through status/command visibility.

## Feature semantics

Backends are expected to honor all feature bits consistently:

- `framebuffer_fetch`
- `explicit_texture_transitions`
- `texture_copy`
- `render_target_blit`
- `frame_capture`
- `float16_render_targets`
- `float32_render_targets`
- `float32_linear_filtering`

Feature gates must be enforced by planners before issuing backend commands.

## Existing conformance coverage

Current renderer-api conformance tests (non-backend):

- `pp_renderer_api_tests`
- `pp_renderer_api` test cases:
  - `validates_texture_usage_contract`
  - `validates_texture_transition_contract`
  - `validates_mipmap_generation_contract`
  - `validates_texture_copy_contract`
  - `validates_blit_contract`
  - `plans_paint_feedback_paths`
  - `renderer_interfaces_support_backend_neutral_dispatch`
  - `recording_renderer_*` command-sequence and validation tests

OpenGL-specific conformance remains in `pp_renderer_gl` suites:

- `pp_renderer_gl_capabilities_tests`
- `pp_renderer_gl_command_plan_tests`
- `pp_renderer_gl_gpu_readback_tests` (where GPU context is available)
- `panopainter_renderer_conformance_matrix_self_test`
- `ctest --preset renderer-conformance`
- `panopainter_renderer_api_contract_self_test` (tooling guard for renderer API and paint renderer
  backend-neutral contract source purity).

## Open items for RND-007

- Ensure Vulkan/Metal planning/lifecycle tests run the same contract surfaces without backend leakage.
- Keep `pp_renderer_api` implementation/usage free from backend-only headers and raw platform state.
- Keep new backend labs opt-in until this contract and conformance matrix are complete.
