Skip to main content

iridia_exec/
request.rs

1//! What an evaluation asks of its caller, and the trait that answers it.
2//!
3//! A request names its resources by `R`: [`Element`] where the program's own interface is the vocabulary
4//! ([`Backend`]), the D3D bind slot where [`crate::Sampler`] answers for a bytecode that counts slots.
5
6use iridia::ResourceId;
7
8/// A resource of the program's interface and, for an array of them (`binding_array`), the element the program's index
9/// picked (0 for a resource that is not an array). An index past a bounded array's length is an error that stops the
10/// evaluation (D3D12 leaves it undefined, so there is no answer to compare); the length of an unbounded array is the
11/// caller's to check.
12#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub struct Element {
14    /// The resource of the program's interface.
15    pub id: ResourceId,
16    /// The element of an array of resources the program's index picked; 0 for a resource that is not an array.
17    pub index: u32,
18}
19
20/// A texture's shape as a request states it.
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22pub enum Dim {
23    /// A one-dimensional texture.
24    D1,
25    /// A two-dimensional texture.
26    D2,
27    /// A three-dimensional texture.
28    D3,
29    /// A cube map.
30    Cube,
31}
32
33/// How a request picks its level of detail. Gradients are three components wide: a 1D or 2D texture leaves the rest 0.
34#[derive(Clone, Copy, Debug, PartialEq)]
35pub enum ImageLod {
36    /// The implicit level, whose footprint a scalar evaluation leaves to the sampler.
37    Implicit,
38    /// The implicit level plus a bias the program states.
39    Bias(f32),
40    /// A level the program states.
41    Level(f32),
42    /// The coordinate's screen derivatives (d/dx, then d/dy): those the program states, or a quad's own for an
43    /// implicit-level sample.
44    Gradients([[f32; 3]; 2]),
45    /// A quad's own derivatives plus the bias the program states.
46    GradientsBias([[f32; 3]; 2], f32),
47}
48
49/// A sample of any texture: 1D, 2D, 3D, cube, arrayed, with an offset, a gather or a comparison.
50#[derive(Clone, Copy, Debug)]
51pub struct ImageSample<R> {
52    /// The texture sampled: an interface [`Element`] or a bind slot, as `R` says.
53    pub texture: R,
54    /// The sampler, named the same way.
55    pub sampler: R,
56    /// The texture's shape.
57    pub dim: Dim,
58    /// The coordinate's components (1D: x; 2D: x, y; 3D and cube: x, y, z); the rest 0.
59    pub coord: [f32; 3],
60    /// An array's layer, as the program gives it (already rounded and clamped to 0 or more).
61    pub layer: Option<f32>,
62    /// How the level of detail is picked.
63    pub lod: ImageLod,
64    /// The constant texel offset (0 where the program states none).
65    pub offset: [i32; 3],
66    /// A gather: the component (0 to 3) whose four texels are returned.
67    pub gather: Option<u8>,
68    /// A comparison sample's reference value.
69    pub depth_ref: Option<f32>,
70    /// The texture is a depth texture: the first lane of the result is its (compared) depth.
71    pub depth: bool,
72}
73
74/// A texel load (`ld`, `ld_ms`, a typed unordered-access load).
75#[derive(Clone, Copy, Debug)]
76pub struct ImageLoad<R> {
77    /// The texture read.
78    pub texture: R,
79    /// The texture's shape.
80    pub dim: Dim,
81    /// A view of an unordered-access resource rather than a shader resource.
82    pub storage: bool,
83    /// The integer address of the texel (x, y, z; the rest 0).
84    pub texel: [i32; 3],
85    /// An array's layer.
86    pub layer: Option<i32>,
87    /// The sample of a multisampled texture.
88    pub sample: Option<i32>,
89    /// The mip level; `None` where the load states none.
90    pub mip: Option<i32>,
91}
92
93/// Which property of a texture a query reads.
94#[derive(Clone, Copy, Debug, PartialEq, Eq)]
95pub enum QueryKind {
96    /// The width, height and depth at `level` (as many as the dimension has).
97    Size,
98    /// The number of mip levels.
99    Levels,
100    /// The number of array layers.
101    Layers,
102    /// The number of samples per texel.
103    Samples,
104}
105
106/// A `resinfo`-style query.
107#[derive(Clone, Copy, Debug)]
108pub struct ImageQuery<R> {
109    /// The texture queried.
110    pub texture: R,
111    /// The texture's shape.
112    pub dim: Dim,
113    /// Which property is read.
114    pub kind: QueryKind,
115    /// The mip level a size is asked at; `None` where the query states none.
116    pub level: Option<u32>,
117}
118
119/// A write to an unordered-access texture.
120#[derive(Clone, Copy, Debug)]
121pub struct ImageStore<R> {
122    /// The unordered-access view written.
123    pub view: R,
124    /// Which view of an array of views (0 for a view that is not in an array).
125    pub index: u32,
126    /// The view's shape.
127    pub dim: Dim,
128    /// The integer address of the texel (x, y, z; the rest 0).
129    pub texel: [u32; 3],
130    /// An array's layer.
131    pub layer: Option<u32>,
132    /// The lanes as the program writes them (bits); only the first `lanes` are written.
133    pub value: [u32; 4],
134    /// How many of the value's lanes the program writes.
135    pub lanes: u8,
136}
137
138/// What an atomic operation on a texel does with the word it holds and the program's value.
139#[derive(Clone, Copy, Debug, PartialEq, Eq)]
140pub enum ImageAtomicOp {
141    /// Add the program's value to the word.
142    Add,
143    /// Subtract the program's value from the word.
144    Sub,
145    /// Bitwise and.
146    And,
147    /// Bitwise or.
148    Or,
149    /// Bitwise exclusive or.
150    Xor,
151    /// The smaller of the two (signed or unsigned, as `ImageAtomic::signed` says).
152    Min,
153    /// The larger of the two (signed or unsigned, as `ImageAtomic::signed` says).
154    Max,
155    /// Store the program's value.
156    Exchange,
157}
158
159/// An atomic operation on one texel of a single-channel 32-bit unordered-access texture. Its result is the word as it was
160/// before; the program reads it when its `Statement::ImageAtomic` has a result.
161#[derive(Clone, Copy, Debug)]
162pub struct ImageAtomic<R> {
163    /// The unordered-access view operated on.
164    pub view: R,
165    /// Which view of an array of views (0 for a view that is not in an array).
166    pub index: u32,
167    /// The view's shape.
168    pub dim: Dim,
169    /// The integer address of the texel (x, y, z; the rest 0).
170    pub texel: [u32; 3],
171    /// An array's layer.
172    pub layer: Option<u32>,
173    /// The operation.
174    pub op: ImageAtomicOp,
175    /// Whether `Min` and `Max` compare the words as signed integers.
176    pub signed: bool,
177    /// The program's operand.
178    pub value: u32,
179}
180
181/// `TraceRay`: a ray shot into an acceleration structure. The payload is the words of the program's payload structure,
182/// which the programs the ray runs read and write; the caller leaves it as the ray's last program did.
183#[derive(Debug)]
184pub struct TraceRay<'a> {
185    /// The interface resource of the acceleration structure.
186    pub scene: ResourceId,
187    /// The ray's flags ([`crate::ray_flags`]).
188    pub flags: u32,
189    /// The instance inclusion mask: an instance is seen when it shares a bit with it.
190    pub mask: u32,
191    /// `RayContributionToHitGroupIndex`: added to the hit group index.
192    pub hit_group_offset: u32,
193    /// `MultiplierForGeometryContributionToHitGroupIndex`: the geometry index is multiplied by it.
194    pub hit_group_stride: u32,
195    /// `MissShaderIndex`: which miss program runs if nothing is hit.
196    pub miss_index: u32,
197    /// The ray's origin in world space.
198    pub origin: [f32; 3],
199    /// The nearest distance along the ray that counts as a hit.
200    pub t_min: f32,
201    /// The ray's direction in world space.
202    pub direction: [f32; 3],
203    /// The farthest distance along the ray that counts as a hit.
204    pub t_max: f32,
205    /// The words of the payload structure.
206    pub payload: &'a mut [u32],
207}
208
209/// `ReportHit`: an intersection program reports a hit at `t` of kind `hit_kind`, with the words of its attributes.
210#[derive(Debug)]
211pub struct ReportHit<'a> {
212    /// The distance along the ray of the hit.
213    pub t: f32,
214    /// The hit kind the intersection program reports.
215    pub hit_kind: u32,
216    /// The words of the hit attributes structure.
217    pub attributes: &'a mut [u32],
218}
219
220/// `CallShader`: run the callable program `index` of the shader table on the words of a parameter structure.
221#[derive(Debug)]
222pub struct CallShader<'a> {
223    /// Which callable program of the shader table.
224    pub index: u32,
225    /// The words of the parameter structure.
226    pub parameter: &'a mut [u32],
227}
228
229/// Everything an evaluation asks of its caller: texture sampling, loads, queries, and the effects of unordered-access
230/// writes. A request the caller cannot answer is an error that stops the evaluation. Reads of buffers need no call:
231/// the buffers are bound before the run.
232pub trait Backend {
233    /// Answer a texture sample with the texel's four lanes, or an error that stops the evaluation.
234    fn sample(&mut self, request: ImageSample<Element>) -> Result<[f32; 4], String>;
235    /// The texel's four lanes as its view returns them: f32 bits for a float view, the integers otherwise.
236    fn load(&mut self, request: ImageLoad<Element>) -> Result<[u32; 4], String> {
237        Err(format!("resource {}: no loads given", request.texture.id.0))
238    }
239    /// Answer a size or level-count query with its lanes.
240    fn query(&mut self, request: ImageQuery<Element>) -> Result<[u32; 4], String> {
241        Err(format!("resource {}: no queries given", request.texture.id.0))
242    }
243    /// Write a texel of an unordered-access texture. The effect is the caller's: it reaches none of this evaluation's
244    /// reads.
245    fn store_image(&mut self, request: ImageStore<ResourceId>) -> Result<(), String> {
246        Err(format!("resource {}: no stores given", request.view.0))
247    }
248    /// `TraceRay`, for a ray tracing pipeline's program: run what the ray hits and misses.
249    fn trace_ray(&mut self, request: TraceRay<'_>) -> Result<(), String> {
250        let _ = request;
251        Err("no ray tracing pipeline given".into())
252    }
253    /// `ReportHit`, for an intersection program: whether the hit was accepted.
254    fn report_hit(&mut self, request: ReportHit<'_>) -> Result<bool, String> {
255        let _ = request;
256        Err("no ray tracing pipeline given".into())
257    }
258    /// `CallShader`, for a ray tracing pipeline's program.
259    fn call_shader(&mut self, request: CallShader<'_>) -> Result<(), String> {
260        let _ = request;
261        Err("no ray tracing pipeline given".into())
262    }
263    /// An atomic operation on one texel; its result the word as it was before.
264    fn atomic_image(&mut self, request: ImageAtomic<ResourceId>) -> Result<u32, String> {
265        Err(format!("resource {}: no image atomics given", request.view.0))
266    }
267    /// Words written to a buffer: the lanes `mask` marks of `value`, to the consecutive 32-bit words from word `word`
268    /// of the buffer. The effect is the caller's: it reaches none of this evaluation's reads.
269    fn store_buffer(&mut self, view: ResourceId, word: u32, value: [u32; 4], mask: u8) -> Result<(), String> {
270        let _ = (word, value, mask);
271        Err(format!("resource {}: no stores given", view.0))
272    }
273    /// `count` (1 to 4) consecutive 32-bit words from word `word` of a buffer the caller did not bind
274    /// ([`super::Resources::buffers`]); lanes past `count` are 0.
275    fn read_buffer(&mut self, view: ResourceId, word: u32, count: u8) -> Result<[u32; 4], String> {
276        let _ = (word, count);
277        Err(format!("resource {}: no buffer given", view.0))
278    }
279    /// How many words a buffer the caller did not bind has.
280    fn buffer_words(&mut self, view: ResourceId) -> Result<u32, String> {
281        Err(format!("resource {}: no buffer given", view.0))
282    }
283    /// An atomic add to word `word` of a buffer; its result the word as it was before.
284    fn atomic_add(&mut self, view: ResourceId, word: u32, value: u32) -> Result<u32, String> {
285        let _ = (word, value);
286        Err(format!("resource {}: no atomics given", view.0))
287    }
288}