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}