iridia-interface
A shader program's interface as plain data: its inputs and outputs, its resources (constant buffers with explicit layouts, textures, samplers, buffers, storage), Direct3D's fixed-function state, and what iridia's analyses observe of the program's code, independent of any graphics API. It depends on serde and nothing else, and every type implements serde::Serialize.
Part of iridia, which turns compiled Direct3D shaders into naga modules. The readers (iridia-dxbc, iridia-dxil, iridia-d3d9, iridia-mojo) map their API's reflection into this once and keep the API's own names and addresses in provenance, so a consumer that only needs meaning (a binding step, a validator, a writer) never sees an API's enum numbers. iridia re-exports it.
What is in it
Interface { stage, inputs, outputs, resources, facts }with oneVaryingper label.labelis the source's own semantic name and index (TEXCOORDand 5) and is not interpreted. D3D packs several varyings into one register; here they are separate, and the register and lanes are inprovenance.d3d.systemis theSystemValuewhen the pipeline supplies or takes it (ClipPosition,FragCoord,FrontFacing,VertexIndex,InstanceIndex,PrimitiveIndex,SampleIndex,Target(n),Depth,Coverage, the compute, ray tracing and mesh built-ins...).valueis aScalarTypeand a width of 1 to 4;interpanInterpolationof mode (perspective, linear, flat) and sampling (centre, centroid, sample) where the source states it;usedsays the program reads or writes some lane.Resource { id, kind, count, provenance }.kindisConstantBuffer { layout },Texture,Sampler,Buffer,Storageor an acceleration structure;countis the length of a resource array (Resource::UNBOUNDEDfor one the program does not size);provenanceholds the source's name and its D3D bind point (classb,t,soru, register, space).- Constant layouts. A
BufferLayoutlists everyConstantwith an explicit byte offset and aConstantTypewhose matrix lines and array elements have stated strides and matrices theirMajorness, so D3D packing, std140 and Direct3D 9 registers can all be written in it.ConstantType::size()is the extent of the data, with no padding after the last line or element. StageFacts: what a hull, domain, geometry, mesh or ray tracing program states beyond its varyings (tessellation domain, partitioning and control point counts; geometry primitive types and output limits; mesh limits; hit groups).- Fixed-function state (
RenderStatewith its blend, depth, stencil, cull, fill and alpha test;SamplerStatewith its filters, addressing and comparison): Direct3D's state, as a source states it, for drawing or sampling a program. The CPU executor (iridia-exec) draws and samples with it, and the Direct3D 9 reader reads sampler state. - What a program's code shows, as
iridia's analyses read it:MatrixLines(whether a matrix constant's lines are rows or columns of the matrix it applies, or why the program does not show which),AlphaComparison(what a discard compares a constant word with) andOutputUse(which lanes of a render target output a discard tests, and whether the target's blend weighs by its alpha); andConstantBufferBinding, the size a source binds a constant buffer with. These are observations; what an input, a constant or an output stands for (a view-projection matrix, an albedo) is the consumer's to decide, in its own terms. ShaderFormat(how a program's bytes are encoded),InstructionCount(how large a program is, in its reader's unit).
Example
An interface is built by a reader, but it is only data; this one is written by hand and serialized:
Guarantees and limits
- Conventions are normalized and the original is kept in provenance: D3D register packing is unpacked into one varying per label, and D3D, std140 and Direct3D 9 constant packings all become explicit byte offsets and strides. Behaviour that differs between APIs is not hidden here at all; that is the program body's business.
- A value a reader cannot map (a
D3D_NAME, a component type, a resource type with a counter, atbuffer) is an error naming it, never a guess. - What the readers keep and drop: DXBC states interpolation in the program's declarations, not its signature, so the standalone reflection leaves
interpempty andiridia_dxbc::liftfills it; DXIL states it in the entry point's metadata. A UAV'saccessisReadWrite(neither reflection says more). A structured buffer is its stride; the element layout is not kept. A DXILhalfand DXBC minimum-precision types are read as 32-bit. - Every type is
Serializeonly; there is noDeserialize.
Tests
cargo test -p iridia-interface needs no game files; the layout arithmetic (ConstantType::size) is tested against sizes worked out by hand, and the render state's consistency check has its own unit tests.
Licence
GPL-3.0-or-later.