Expand description
A reader of Direct3D 9 shader bytecode: the token stream a Direct3D 9 compiler or assembler writes for a vertex or
pixel program of Shader Model 1.x, 2.x or 3.0, from its version token to END, with no container around it.
read decodes the stream into typed records in stream order (Program::items): every comment, every
declaration (dcl), every literal definition (def, defi, defb) and every instruction with its opcode, control
bits, co-issue and predicate, destination (register, write mask, saturate, partial precision, centroid, the pixel 1.x
result shift) and sources (register, swizzle, modifier, relative address). The CTAB comment D3DX writes is decoded
as well (ConstantTable), and so is the DBUG comment of a /Zi build (DebugInfo). frame reads the first program of a buffer that holds more after it.
It reads and checks bytes and never interprets them for an API: registers are Direct3D’s register types and numbers,
modifiers and usages Direct3D’s own values. Whatever the format does not define (an opcode outside the instruction
set of the program’s version, a register type it has no name for, a reserved bit set, an instruction whose length
disagrees with its operands) is an Error naming the 32-bit word where it is; it never panics on untrusted input.
// ps_2_0: dcl t0.xy; dcl_2d s0; texld r0, t0, s0; mov oC0, r0; end
let words: [u32; 14] = [
0xffff_0200,
0x0200_001f, 0x8000_0000, 0xb003_0000,
0x0200_001f, 0x9000_0000, 0xa00f_0800,
0x0300_0042, 0x800f_0000, 0xb0e4_0000, 0xa0e4_0800,
0x0200_0001, 0x800f_0800, 0x80e4_0000,
];
let bytes: Vec<u8> = words.iter().chain(&[0xffff]).flat_map(|w| w.to_le_bytes()).collect();
let program = d3d9_reader::read(&bytes)?;
assert_eq!(program.version.to_string(), "ps_2_0");
assert_eq!(program.declarations().count(), 2);
let names: Vec<_> = program.instructions().map(|i| i.opcode.name()).collect();
assert_eq!(names, ["tex", "mov"]);Structs§
- Comment
- A comment: its words, without its token. The constant table is one, its first word the FourCC
CTAB. - Constant
- A named allocation, including the original type even when optimization shortened its register range.
- Constant
Table - The constant table (CTAB comment) of a program: who compiled it, for which target, and the named register allocations.
- Debug
Info - The
DBUGcomment decoded. - Declaration
- A
dcl: the declaration token and the register declared. - Definition
- A
def,defiordefb: a constant register and the literal it holds. - Destination
- A destination operand.
- Error
- Something the reader can’t read: the 32-bit word of the token stream where it is (the version token is word 0), and what was expected there or found instead.
- Instruction
- An instruction: everything but declarations, definitions, comments and
END. - Location
- Where an instruction writes a variable: the variable’s components in its four destination lanes.
- Options
- What the listing writes, as the
D3D_DISASM_*flags of Microsoft’s disassembler choose it. - Program
- A program read: its version, its records in stream order, its constant table and its debug information.
- Records
- A program’s records in stream order: see
records. - Register
- A register: its type and number.
- Relative
- The index register of a relatively addressed operand (
c[a0.x + 4],v[aL]). - Source
- A source operand.
- Source
Line - The source line of one declaration, definition or instruction.
- Type
- A CTAB type. Numeric class/type values are D3DXPARAMETER_CLASS/TYPE, kept alongside their dimensions.
- Type
Member - One member of a struct type.
- Variable
- A variable: a parameter, a local, the function’s return value or a constant.
- Version
- A program’s version token: the stage, and the major and minor version in its low 16 bits.
Enums§
- Comparison
- The comparison of
if_comp,break_compandsetp_comp(D3DSHADER_COMPARISON), bits 16 to 18 of the instruction token. - Declared
- What a declaration token declares.
- Item
- One record of the stream.
- Literal
- The literal of a definition.
- Modifier
- A source modifier (
D3DSHADER_PARAM_SRCMOD_TYPE,D3DSPSM_*), bits 24 to 27 of a source token. - Opcode
- An instruction opcode: the low 16 bits of an instruction token. The variants carry the token value
(
Opcode::code) and the assembler’s name (Opcode::name); declarations (dcl), definitions (def,defi,defb), comments andendare opcodes of the stream as well but are read into their own records. - Register
Type - A register type (
D3DSHADER_PARAM_REGISTER_TYPE,D3DSPR_*). Type 3 is the address register in a vertex program and a texture register in a pixel program; type 6 is a vertex program’s texture-coordinate output (oTN) before 3.0 and its outputoNin 3.0. - Stage
- The stage a program is for: the high 16 bits of its version token,
0xfffevertex and0xffffpixel. - Texture
Type - A sampler’s texture type (
D3DSAMPLER_TEXTURE_TYPE), bits 27 to 30 of its declaration token.
Functions§
- disassemble
- The listing of a Direct3D 9 program (its version token to
END, no container) as Microsoft’s disassembler writes it with no flags, its lines ending in\n(the disassembler’s blob also ends in a zero byte, which is not part of the text). Refuses whatreadrefuses. - disassemble_
with - The listing
disassemblewrites, with whatoptionschoose. - frame
- Read the first program of
bytes, which may hold more after it (a container’s other records, say), and return it with its exact bytes, version token toEND.ENDis found by reading every record, never by searching for it inside operands or comments. - read
- Read a complete program: version token to
END, with nothing after it. The bytes are little-endian words. - records
- The records of a complete program, one at a time in stream order, for a caller that stops at the first record it
cannot use, before the reader has read further (and refused, maybe, something later). The version is read first;
a refusal ends the iteration, as does
END, after which words left over are a refusal.readis these records collected.