khora_core/lane/
context_keys.rs

1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Domain-agnostic context key types for [`LaneContext`](super::LaneContext).
16//!
17//! These newtypes are inserted into a `LaneContext` by agents and extracted
18//! by lanes. Placing them in `khora-core` avoids a cyclic dependency between
19//! `khora-lanes` and `khora-agents`.
20//!
21//! # Render domain
22//!
23//! | Key                          | Meaning                                      |
24//! |------------------------------|----------------------------------------------|
25//! | [`ColorTarget`]              | Texture view to render colour into            |
26//! | [`DepthTarget`]              | Texture view for depth testing                |
27//! | [`ClearColor`]               | Framebuffer clear colour                      |
28//! | [`ShadowAtlasView`]          | Shadow atlas view written by shadow lanes     |
29//! | [`ShadowComparisonSampler`]  | PCF comparison sampler for shadow sampling    |
30//!
31//! # Physics domain
32//!
33//! | Key                  | Meaning                           |
34//! |----------------------|-----------------------------------|
35//! | [`PhysicsDeltaTime`] | Fixed timestep for the current step |
36//!
37//! # Audio domain
38//!
39//! | Key                | Meaning                               |
40//! |--------------------|---------------------------------------|
41//! | [`AudioStreamInfo`]| Sample rate, channels, etc.           |
42//! | [`AudioOutputSlot`]| Mutable borrow of the output buffer   |
43
44use crate::renderer::api::resource::{SamplerId, TextureViewId};
45
46// ─────────────────────────────────────────────────────────────────────────────
47// Render domain
48// ─────────────────────────────────────────────────────────────────────────────
49
50/// Color render target for the current frame.
51#[derive(Debug, Clone, Copy)]
52pub struct ColorTarget(pub TextureViewId);
53
54/// Depth render target for the current frame.
55#[derive(Debug, Clone, Copy)]
56pub struct DepthTarget(pub TextureViewId);
57
58/// Clear color for the current frame.
59#[derive(Debug, Clone, Copy)]
60pub struct ClearColor(pub crate::math::LinearRgba);
61
62/// Shadow atlas texture view, written by shadow lanes after `execute()`.
63#[derive(Debug, Clone, Copy)]
64pub struct ShadowAtlasView(pub TextureViewId);
65
66/// Shadow comparison sampler, written by shadow lanes after `execute()`.
67#[derive(Debug, Clone, Copy)]
68pub struct ShadowComparisonSampler(pub SamplerId);
69
70// ─────────────────────────────────────────────────────────────────────────────
71// Physics domain
72// ─────────────────────────────────────────────────────────────────────────────
73
74/// Fixed timestep for the current physics step.
75#[derive(Debug, Clone, Copy)]
76pub struct PhysicsDeltaTime(pub f32);
77
78// ─────────────────────────────────────────────────────────────────────────────
79// Audio domain
80// ─────────────────────────────────────────────────────────────────────────────
81
82/// Audio stream info (sample rate, channel count, etc.).
83///
84/// Re-exports [`crate::audio::device::StreamInfo`] as a context key.
85/// Agents insert `AudioStreamInfo(stream_info)` into the context.
86#[derive(Debug, Clone, Copy)]
87pub struct AudioStreamInfo(pub crate::audio::device::StreamInfo);
88
89/// Mutable borrow of the audio output buffer via raw pointer.
90///
91/// This wraps a `*mut [f32]` so it can be stored in [`LaneContext`](super::LaneContext).
92///
93/// # Safety
94///
95/// Same frame-scoped guarantees as [`Slot`](super::Slot).
96pub struct AudioOutputSlot {
97    ptr: *mut f32,
98    len: usize,
99}
100
101// SAFETY: frame-scoped, single-lane-at-a-time.
102unsafe impl Send for AudioOutputSlot {}
103unsafe impl Sync for AudioOutputSlot {}
104
105impl AudioOutputSlot {
106    /// Creates a new `AudioOutputSlot` from a mutable slice.
107    pub fn new(buffer: &mut [f32]) -> Self {
108        Self {
109            ptr: buffer.as_mut_ptr(),
110            len: buffer.len(),
111        }
112    }
113
114    /// Returns a mutable slice to the output buffer.
115    ///
116    /// # Safety contract
117    ///
118    /// Safe when called within the scope where the original slice is alive.
119    #[allow(clippy::mut_from_ref)]
120    pub fn get(&self) -> &mut [f32] {
121        // SAFETY: guaranteed by frame-scoped execution
122        unsafe { std::slice::from_raw_parts_mut(self.ptr, self.len) }
123    }
124}