Expand description
Compiled Direct3D shaders as naga modules, so they can be validated, inspected and written as WGSL, SPIR-V or
whatever else a naga backend writes.
This is the crate every bytecode reader of the iridia workspace lifts into. A Program is a naga::Module with
what a module cannot say: an Interface (inputs and outputs by semantic name with their D3D register and lanes
kept in provenance, constant buffers with explicit layouts, textures, samplers and buffers), the clip-space and
texture-origin Conventions it was written for, which of Direct3D’s numeric behaviours its body spells out
(D3dModes) and where it came from (Provenance). The readers are separate crates:
iridia-dxbc (Shader Model 4 and 5), iridia-dxil (Shader Model 6), iridia-d3d9 (raw Shader Model 2 and 3
tokens) and iridia-mojo (the GLSL MojoShader writes from Shader Model 2 and 3).
§Example
Lift a compiled pixel shader, check it and write WGSL (iridia-dxbc is a development dependency of this crate; a
program of your own depends on it directly):
let container = include_bytes!("../../iridia-dxbc/tests/fixtures/modes.dxbc");
let program = iridia_dxbc::lift(container)?;
assert_eq!(program.stage, iridia::Stage::Pixel);
assert_eq!(program.provenance.target, "ps_5_0");
// the constant buffer `C` of the HLSL source, named by the container's reflection
assert_eq!(program.interface.resources[0].provenance.name, "C");
program.validate().expect("a lifted program validates");
let wgsl = iridia::emit::wgsl(&program)?;
assert!(wgsl.contains("@fragment"));§What is here
Program, itsvalidate(naga’s validation, then the interface against the entry point and the resources against the module’s globals) andtext(a stable text form, for diffs);emit: WGSL writers, andemit::wgsl_for, WGSL as one pipeline binds it;build::Builder, the typed builder over naga’s IR the readers lift with, andbuild::structure, which turns a control flow graph into structured control flow;d3d: Direct3D’s enum numbers and packing rules mapped into theiridia_interfacevocabulary, shared by the DXBC and DXIL readers;Refusal: what every reader returns for bytecode it cannot lift, naming where and why;gate: the version check a reader’s tests use so that a changed output comes with a bumped version number;- analyses of a lifted program, none of which runs it:
flow(what each output lane is made of),matrix(how a constant buffer holds a matrix),output_storesandoutput_uses(what the entry point stores into its outputs and what a discard or blend shows a lane is used for), andProgram::constant_reads(which constant words it reads); rt: the calls a ray tracing program makes in place of the pipeline’s operations.
Running a program on the CPU is the iridia-exec crate.
The vocabulary types are those of iridia_interface, re-exported here.
Re-exports§
pub use bound::BoundSizes;
Modules§
- blend
- Layers a program lays over one another, read from its value graph (
Values) with no game in it: a lane that is a chain of interpolations, each towards a layer’s value by a weight (Over), and any scalar value as the float operations it is made of (Scalar), down to the nodes the caller says what they are of (an input lane, a texel, a constant word). - bound
- The size a constant buffer is bound with.
- build
- A typed builder over naga’s IR for lifters. Every value it hands out carries its scalar kind and width, so a lifter
never asks naga’s typifier and a bitcast or splat is explicit where it is needed. Nothing here knows a bytecode;
behaviourholds D3D’s results spelled out as operations. - d3d
- D3D’s enum numbers and packing rules, mapped into the vocabulary (
iridia_interface). The DXBC and DXIL readers share them: both state signatures and constant buffers in D3D’s terms. Nothing here is evaluation; a number the table does not map is refused with its name (anErrthe reader reports), never guessed. - emit
- Writers: a
Programas source text for another API. A writer that cannot express a program refuses it with the reason; it never approximates. - flow
- What a program’s outputs are made of: a dataflow query over the lifted module, with no game in it.
- gate
- The version gate of a lifter. A lifter’s
LIFTER_VERSIONand the program representation’scrate::PROGRAM_VERSIONare what a cache keyed by a bytecode’s hash trusts to know that a program it holds is stale, so a change to what a lifter makes of a bytecode must come with a bump. The gate makes that checkable: a lifter’s tests lift its committed fixtures,tablehashes each outcome (the program’s stable text form, or the refusal) under the versions the lifter has, the table is committed, andcheckfails when the outcomes changed and the versions did not (bump the one that names the change), or the versions changed and the committed table is not that version’s. - matrix
- How a program holds a matrix in a constant buffer: the arrangement of its lines, read from what the program does.
- output_
stores - What a program’s entry point stores into its outputs, lane by lane, read from its lifted module: for each output the
interface declares, the local variable the entry point’s result takes it from, and the stores into that variable’s
lanes, in every branch.
OutputStoresgives a colour target’s lanes (SV_Target<n>) and the constant rows an output is made of, and tests how a stored value is made (x * 0.5 + 0.5,floor(x) / 256, a square root, the constant 0), seeing through the bit casts the lifters write every output word with and the loads of a local variable assigned once. Nothing here is read from a program’s name or a local’s name; what the lanes mean is for the caller to say. - output_
uses - What a pixel program’s own discards and its targets’ stated blend show its output lanes are used for
(
output_uses), and what its discards compare a constant word with (discard_compares,alpha_tests). These are observations of the program and its state; what they make a lane or a word stand for is the caller’s to decide. Nothing is read from a program’s or a target’s name. - rt
- The ray tracing pipeline’s operations. WGSL has no ray tracing pipeline and naga’s has no
ReportHit,IgnoreHit,CallShaderor hit-group indices, so a ray tracing program (seecrate::stage_functions) does what the pipeline does for it by calling functions of its own module that have no body: the call is the operation, the arguments its operands, and a consumer that traces rays reads the calls. A stub’s body is empty (a function that returns a value returnsfalse), so nothing that runs the module as written runs the pipeline. - specialise
- Conservative material specialisation. Only explicitly supplied uniform words are constants. The original program remains unchanged; unsupported control flow is refused rather than guessed.
Structs§
- Buffer
Layout - A constant buffer’s contents.
- Constant
- One named constant of a buffer.
- Conventions
- The pipeline rules a program was written for, declared where it meets the pipeline (the vertex stage’s clip position, the pixel stage’s fragment position and texture coordinates) and applied once at that boundary by whoever runs it on another API’s rules; the body itself is never rewritten for them.
- D3dBinding
- A D3D bind point: class, register index and register space.
- D3dModes
- Which of D3D’s behaviours the body spells out. The IR’s own results for these differ between the APIs that lower to it (WGSL defines integer division by zero as the dividend, SPIR-V leaves it undefined), so a D3D lifter writes D3D’s answer as plain operations and says it did: a consumer that finds a flag unset knows the body takes the IR’s answer there, and a writer never has to guess.
- D3dSignature
- Where a D3D signature element sits: its register (four 32-bit lanes each) and the lanes of it the element occupies, as a mask (bit k is lane k, x first), and the signature’s read/write mask as stored.
- Domain
Facts - What a domain program states about its patch: the same domain as the hull program that feeds it, how many control
points it reads, and the patch-constant varyings it reads (
inputsof the interface are its control points’). - EntryIo
- The entry point’s arguments (one per input varying) and result members (one per output varying, the clip distances
being one together), in interface order. A varying nothing reads or writes (
usedfalse) that no binding exists for is left out: the interface lists every element of the container’s signature, the module carries what it can. - FnItem
- One argument or result member of a stage function.
- Function
Sig - A function of a program that has no entry point: its name, arguments and result members (a structure
Outwhen there are any). - Geometry
Facts - What a geometry program states: the primitive it reads, what its emitted vertices make, the most vertices an invocation emits and how many invocations run for a primitive.
- HitGroup
- A hit group of a ray tracing library: the programs it runs, named by the library’s exports (none where the group has no such program).
- Hull
Facts - What a hull program states about its patch beyond its varyings. The patch-constant varyings are its outputs per
patch (
SV_TessFactor,SV_InsideTessFactor, whatever the domain program reads);outputsof the interface are its control points’. - Instruction
Count - How many instructions a program has, in the unit that says how they were counted.
- Interface
- What a program exposes: its stage, the varyings it takes and gives, and the resources it binds.
- Interpolation
- A pixel input’s interpolation: the mode and the sampling location.
- IoItem
- One argument or result member.
- Label
- A varying’s name in its source: the semantic name and its index (DXBC
TEXCOORDand 5, SPIR-VLocationand 3, GLSLvUvand 0). Labels are not interpreted: games put anything inTEXCOORDn, and what a label means is the consumer’s business. Stages match by label. - Member
- A structure’s member: its offset is from the start of the structure.
- Mesh
Facts - What a mesh program states: what its primitives are and the most vertices and primitives it writes. Its thread group size is the entry point’s, as a compute program’s is.
- Program
- A shader program: the module, and what the module cannot say.
- Program
Graph - What a binding takes from a lifted program: its value graph, the interface the graph names resources by (a program lifted again may number them otherwise than a stored interface), and the constant words its results are made of.
- Provenance
- Where a program came from.
- RayTracing
Facts - What a ray tracing program’s library states: the program’s own export name (as the subobjects name it) and every subobject of the library, in the order it stores them. A pipeline is built from a library’s programs and these.
- Refusal
- A program a lifter did not lift, or a container it could not read: the bytecode, where in it and the reason, by name.
The reason is stated whole, numbers included;
Refusal::groupis the key to count refusals by. - Resource
- One bound resource.
- Resource
Id - Names a resource within one
super::Interface; the reader numbers them in its source’s order. - Resource
Provenance - The source’s own name and address for a resource; one field per API that has a notion of it.
- Value
- A scalar type and a width of 1 to 4 lanes.
- Varying
- One interface variable: a value passed between stages (or between a stage and the pipeline), one per label. D3D packs several into one register; they are separate here, with the register and lanes kept in provenance.
- Varying
Provenance - The source’s own address of a varying; one field per API that has a notion of it.
- Words
Read - The words of each constant buffer a program’s results are made of: every word some output lane, discard condition
or write (
Values::writes) of the value graph reaches back to, at the word’s place in the buffer (rowr, lanelis word4r + l). A buffer read at an index computed at run time may be read at any word. A word a computation reads and nothing uses is not read. The reads are what the program may use, not what it must: a word multiplied by zero at run time still counts.
Enums§
- Access
- What a program may do to a storage resource.
- Buffer
Kind - How a buffer’s elements are addressed.
- Clip
Depth - Which way clip space’s depth runs.
- Constant
Type - The type of one constant, with the layout it has in its buffer written out: vectors are tightly packed lanes, every matrix line and array element sits at a stated stride, whatever packing rules (D3D, std140, std430, DX9 registers) put it there.
- D3dClass
- The register class of a D3D binding:
b,t,soru. - GsInput
- The primitive a geometry program reads.
- GsOutput
- What a geometry program’s emitted vertices make.
- HitGroup
Kind - What a hit group runs for the geometry it is bound to.
- Instruction
Unit - The source’s counting unit. DXBC counts decoded instructions including control flow, excluding declarations; DXIL counts LLVM instructions in the functions the lifter reads. Neither is an executed instruction count or an IR expression count.
- Interp
Mode - How a varying is interpolated across a primitive.
- Interp
Sampling - Where in a pixel a varying is sampled.
- IoType
- The type of an entry point argument or result member.
- Item
List - What a
FnItemcarries. - Majorness
- Whether consecutive lines of a matrix are its rows or its columns.
- Mesh
Topology - What a mesh program’s primitives are.
- Origin
- Which way a vertical axis runs.
- Partitioning
- How the tessellator spaces the vertices it adds along an edge.
- Problem
- One rule a program broke.
- Program
Error - What can go wrong building, checking or writing a program.
- Resource
Kind - What a resource is.
- Sample
Type - What a texture returns when it is read.
- Scalar
Type - The scalar type of a value or constant.
- Shader
Format - How a shader program’s bytes are encoded. Only the encoding lives here; reading one is the job of the crate that
knows it (
iridia-dxbc,iridia-dxil,iridia-d3d9,iridia-mojo), and the program’s meaning is lifted from it on demand. - Stage
- The pipeline stage a program runs in.
- Stage
Facts - Facts about a program a stage’s varyings and resources do not carry.
- Storage
Target - What a storage resource is.
- Subobject
- A state object subobject of a ray tracing library, as the library declares it.
- System
Value - The system values, one vocabulary for every API: what the pipeline itself supplies to or takes from a stage.
- Tess
Domain - The shape a tessellator gives a patch.
- Tess
Topology - What the tessellator emits.
- Texture
Dim - The dimensionality of a texture or image. Whether it is an array or multisampled is separate.
- Unit
- What an offset in a
Refusalor ancrate::Origincounts, in the source’s own terms.
Constants§
- PROGRAM_
VERSION - The version of the program representation: bumped when what a program means changes (a convention, a mode, how
the module carries the interface). Each lifter’s tests hash what it makes of its fixtures under this and its own version
(
iridia::gate), so a change that moves them without a bump of one of the two fails. - WEBGPU_
BASELINE - WebGPU’s default limits: invocations per workgroup, size along x, y and z, and bytes of workgroup memory.
Functions§
- compute_
limit_ notes - Notes for a module whose compute entry point exceeds
WEBGPU_BASELINE: empty when it fits. - entry_
io - The entry point’s arguments and result members for
interface.Errsays why the module cannot carry it (a system value no stage binding exists for). - interface_
notes - Notes for an interface that carries something WebGPU has no built-in for.
- mesh_
vertex_ io - The members of a mesh program’s vertex type, one for each output varying, bound as a vertex program’s outputs are.
- source_
hash - The hash of the bytes a lifter was given (
sha256:and 64 hexadecimal digits), which a program keeps as its source’s identity incrate::Provenance::source_hash: the lifter computes it, the caller does not state it. - stage_
functions - The functions a program of a stage naga has no entry point for is made of;
Nonefor a stage that is an entry point. The arguments carry no bindings: they are named after the varying they carry, as an entry point’s are.