iridia_interface/binding.rs
1//! What a program's own code shows of how it uses what it is bound: how a constant buffer's lines hold a matrix, what a
2//! discard compares a constant with, and what an output's lanes are tested or blended by. These are observations the
3//! analyses of `iridia` make (`iridia::matrix`, `iridia::output_uses`), held as plain data so that a consumer without
4//! naga can keep them; what an observation makes a value stand for is the consumer's to decide.
5
6use serde::Serialize;
7
8use crate::{Label, ResourceId};
9
10/// What a discard compares against a constant word (an alpha reference), proved from the program's data flow
11/// (`iridia::output_uses::discard_compares`).
12#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
13#[serde(rename_all = "snake_case")]
14pub enum AlphaComparison {
15 /// The output alpha itself (including unchanged branch arms).
16 Output,
17 /// A scalar that reaches output alpha through arithmetic. Cutting the output is an approximation.
18 Transformed,
19 /// A pre-transform alpha plus `(dither.a - 0.5) * scale`. `scale_word` is a word offset in the reference's own
20 /// buffer. A hard cutoff on output alpha approximates the program's stochastic, pre-transform test.
21 Dithered {
22 /// Word offset of the dither scale in the reference's own buffer.
23 scale_word: u32,
24 },
25 /// The discard compares a value made of texture samples and constants that reaches no target's alpha (a G-buffer
26 /// program writes none: `t1.w * t0.w + scale * (noise - 0.5) < reference`). The test is the program's own
27 /// expression, read exactly from its graph (`iridia::output_uses::alpha_tests`); a cutoff on any output alpha is not
28 /// it, and a consumer that cuts evaluates that expression, or does not cut.
29 Unwritten,
30}
31/// How a matrix constant's 16-byte lines hold the matrix the program applies to column vectors (a view-projection's
32/// clip position is `M * p`). The layout's packing (`row_major`, `column_major`) does not decide it, since a program may
33/// multiply on either side (`mul(M, v)`, `mul(v, M)`): `iridia::matrix::lines_at` reads it from what the program does.
34#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
35#[serde(rename_all = "snake_case")]
36pub enum MatrixLines {
37 /// Each line is one of the matrix's rows.
38 Rows,
39 /// Each line is one of its columns.
40 Columns,
41 /// The program does not show which, and why ([`Unshown`]). A consumer that writes a matrix unequal to its
42 /// transpose (a camera's) cannot bind it; one that writes the identity can.
43 Unshown(Unshown),
44}
45/// Why a program does not show a matrix's lines ([`MatrixLines::Unshown`]): the kind a consumer branches on, its text
46/// ([`std::fmt::Display`]) the reason.
47#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
48#[serde(rename_all = "snake_case")]
49pub enum Unshown {
50 /// Its results are made of none of the matrix's words.
51 NotRead,
52 /// It reads them but sums no product of them with other values: it does not apply the matrix.
53 NotApplied,
54 /// It applies the matrix both ways: `along` sums of one line's words, `across` of one lane's.
55 BothWays {
56 /// How many sums of the words of one line there are.
57 along: usize,
58 /// How many sums of the words of one lane across lines there are.
59 across: usize,
60 },
61 /// The program could not be examined for it, and `why`: its value graph could not be built, or the matrix's buffer
62 /// could not be found in it.
63 Unexamined {
64 /// Why the program could not be examined.
65 why: String,
66 },
67}
68impl std::fmt::Display for Unshown {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 match self {
71 Unshown::NotRead => f.write_str("the program's results are made of none of the matrix's words"),
72 Unshown::NotApplied => f.write_str(
73 "the program sums no product of the matrix's words with other values: it does not show how it \
74 applies the matrix",
75 ),
76 Unshown::BothWays { along, across } => write!(
77 f,
78 "the program applies the matrix both ways: {along} sums of one line's words and {across} of one lane's"
79 ),
80 Unshown::Unexamined { why } => f.write_str(why),
81 }
82 }
83}
84/// What the source states of how it binds a constant buffer of the program, beyond what its constants are.
85///
86/// A program declares a constant buffer at the size it indexes it, and a source can bind more: D3D12 bounds a constant
87/// buffer read by the size of the view the draw binds (the CBV's `SizeInBytes`), not by the shader's declaration, so a
88/// skinning palette a program declares as two matrices is bound as the hundreds the draw uploads, and a joint index past
89/// the declaration reads the palette, not zero. A lifter takes the rows of a buffer's uniform array from the bound size
90/// when it has one (`iridia::BoundSizes`).
91#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
92pub struct ConstantBufferBinding {
93 /// A constant buffer resource of the shader.
94 pub resource: ResourceId,
95 /// The bytes the source binds the buffer with, more than the program declares and a whole number of 16-byte rows;
96 /// `None` is the declared size. Where the engine binds different sizes for different draws, the largest it binds:
97 /// a consumer that fills fewer rows leaves the rest zero.
98 pub bound_size: Option<u32>,
99}
100/// What a pixel program's code and its target's stated blend show of the lanes of one output that is a render target
101/// (`iridia::output_uses::output_uses`): observations, not roles. Each is a lane mask, bit k lane k.
102#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
103pub struct OutputUse {
104 /// The output.
105 pub label: Label,
106 /// The render target it is written to: its system value `SV_Target<n>`, or its label's index where it has none.
107 pub target: u32,
108 /// Lane 3 where the target's stated blend weighs the colour by the source alpha (the colour equation's source or
109 /// destination factor is `SrcAlpha` or `OneMinusSrcAlpha`), else none.
110 pub blend_weight: u8,
111 /// The lanes whose written value is among what a discard's conditions are made of. A literal is no evidence (equal
112 /// literals are one node of the value graph); none where the program's value graph was not given.
113 pub discard_tested: u8,
114}