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}