Expand description
Reader for the DXBC container, the file format Direct3D shader programs are stored in: Shader Model 4 and 5 programs
(SHDR, SHEX, signatures, RDEF) and Shader Model 6 programs (DXIL, PSV0, RDAT, …) alike. chunks reads
the container’s part directory and checksum computes the digest the compiler stores in it. feature_flags
reads the SFI0 part, the shader’s required features, with names for the bits (feature_name). serialize
writes parts as a container with a correct digest, repair_digest fixes the digest of one edited in place, and
replace_part swaps one part of a container for new bytes.
The layout: a header (DXBC, a 16-byte digest, version 1, the container’s size, the number of parts), the directory of
the parts’ offsets right after it, then the parts one after another in the directory’s order, each its four-character
kind, its length and its bytes, the last ending where the container does. Shader Model 6 parts are not padded to 4
bytes, so an offset need not be a multiple of 4. This holds for every fixture committed in dxbc-reader and dxil-reader
(the tests read each to its exact end and compare checksum with the stored digest).
The reader reads to the exact end: a part anywhere else, a gap, a byte after the last part, a kind twice, a size other
than the container’s or a version other than 1 is an Error naming the byte. The digest is not verified (it is not an
authenticity check); checksum is for a caller that wants to compare it.
// A container with one empty `ISGN` part: header, one directory entry, the part.
let mut bytes = b"DXBC".to_vec();
bytes.extend_from_slice(&[0; 16]); // digest
for word in [1u32, 44, 1, 36] {
bytes.extend_from_slice(&word.to_le_bytes()); // version, size, part count, the part's offset
}
bytes.extend_from_slice(b"ISGN");
bytes.extend_from_slice(&0u32.to_le_bytes()); // the part's length
let parts = dxcontainer::chunks(&bytes).expect("a well-formed container");
assert_eq!(&parts[0].kind, b"ISGN");
assert!(parts[0].data.is_empty());
assert!(dxcontainer::checksum(&bytes).is_some());Structs§
- Chunk
- A part of a container: its four-character kind and its bytes.
- Error
- What is wrong with a container, and where (a byte offset in it).
- Feature
Flags - A container’s shader feature flags: its
SFI0part (eight bytes, a little-endianu64) and the bytecode that says what the bits mean. - Write
Error - A container that cannot be written: what is wrong with the parts it was asked to hold.
Enums§
- Bytecode
- Which bytecode a container’s program part holds. It decides what the bits of the container’s
SFI0part name: the two compilers share the first bits and then diverge. - Replace
Error - Why
replace_partfailed: the container it was given, or the container it would write.
Functions§
- checksum
- The digest a container stores at bytes 4 to 20: MD5’s block function over its bytes from 20 on, the last block padded as the
compiler does (the bit count first, then the rest,
0x80, zeros, and at 60 the bit count over 4, or 1; a rest of 56 bytes or more padded in a block of its own first).Nonefor fewer than 20 bytes. - chunks
- The part directory of the container
bytes, in the container’s order. See the module documentation for what is refused. - feature_
flags - The shader feature flags of
container:Nonefor a container with noSFI0part (Sekiro’s and Riders Republic’sDXBCcontainers have none; the part is there in all 69,728DXILcontainers of skate. and Elden Ring). Refuses a containerchunksrefuses, anSFI0part of other than eight bytes, and anSFI0part in a container whose bytecode is unknown (no program part, or both kinds): the bits mean nothing without it. - feature_
name - The name of bit
bitof theSFI0shader feature flags ofbytecode,Nonefor a bit with no name here. - repair_
digest - Rewrites the digest at bytes 4 to 20 of
containerto the onechecksumcomputes over the rest of it: for a container whose bytes were edited in place. Refuses bytes that are not a container’s (fewer than 20, or not startingDXBC), or too long for the digest’s 32-bit bit count. - replace_
part containerwith the part of kindkindreplaced bydata(a part not in it is appended after the others), every other part kept in its place and as it was, and the digest repaired: the edit a shader patch makes. Refuses a containerchunksrefuses.- serialize
- Writes
partsas a container: the header, the directory of the parts’ offsets, then the parts in the order given, each its kind, its length and its bytes with nothing between them, and the digestchecksumcomputes over the result. A part’s bytes are written exactly as given, so a part whose producer padded it (or did not) stays so, andserialize(&chunks(bytes)?)isbytesagain wheneverbytesstores the digestchecksumcomputes, as the games’ shipped containers do. Refuses a kind twice (the containerchunksreads has each kind once) and a size or count that does not fit the header’s 32 bits.