Changes

Jump to navigation Jump to search
5,697 bytes added ,  02:45, 13 August 2021
m
no edit summary
Line 1: Line 1:  
[[Category:File formats]]
 
[[Category:File formats]]
== Overview ==
     −
The SHBIN (SHader BINary) file is used to contain compiled and linked shader programs. These can include vertex shaders (typically compiled from .vsh files) and geometry shaders (typically compiled from .gsh files, though .asm have been observed).
+
The SHBIN (SHader BINary) format is used to contain compiled and linked shader programs. These can include vertex shaders and geometry shaders. In commercial applications, SHBIN files can be found as standalone files with the extension .shbin, or within container formats like, for example, [[CGFX]] (with the extension .bcsdr). They are typically compiled from .vsh files, .gsh files, and sometimes .asm files.
In commercial games/apps, SHBIN files can be found as standalone files with the extension .shbin, or contained within .bcsdr files. BCSDR files use CGFX as a container, but the underlying DVLB/DVLP/DVLE structure remains unchanged.
     −
A SHBIN's structure starts with a header, then a DVLP, then DVLE(s).
+
A SHBIN's structure starts with a binary header (DVLB), then a single program header (DVLP), then one or more executable headers DVLE(s). The binary header specifies the number and location of DVLEs. The program header specifies the generic parts of the shader (i.e. the shader program data, the operand descriptor data, and a filename symbol table). The executable headers specify the contextual details (i.e. entry point, constant values, debug symbols, etc). There may be multiple executable headers, so in this sense multiple shaders sharing the same program code can be stored in a single SHBIN. Hence for the following, note the distinction between "program" and "executable".
   −
== DVLB Header ==
+
For a description of the instruction set, see the following page : [[Shader Instruction Set]]
 +
 
 +
== Header ==
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 29: Line 29:  
|}
 
|}
   −
The DVLP file comes directly after the header.
+
The DVLP section comes directly after the binary header.
    
== DVLP ==
 
== DVLP ==
Line 45: Line 45:  
|  0x4
 
|  0x4
 
|  0x4
 
|  0x4
? (Maybe a version number?)
+
Unknown, same value as in DVLE. (Likely a version number)
 
|-
 
|-
 
|  0x8
 
|  0x8
Line 57: Line 57:  
|  0x10
 
|  0x10
 
|  0x4
 
|  0x4
|  Offset (relative to DVLP start) to shader instruction extension table
+
|  Offset (relative to DVLP start) to operand descriptor table
 
|-
 
|-
 
|  0x14
 
|  0x14
 
|  0x4
 
|  0x4
|  Number of shader instruction extension table entries (each entry is 8-byte long)
+
|  Number of operand descriptor table entries (each entry is 8-bytes long)
 
|-
 
|-
 
|  0x18
 
|  0x18
 
|  0x4
 
|  0x4
Offset (relative to DVLP start) to filename symbol table
+
Unknown (Same value as offset to filename symbol table?)
 
|-
 
|-
|}
+
| 0x1C
 
+
|  0x4
== Instructions ==
+
| Unknown (Always zero?)
 
  −
=== Encoding ===
  −
{| class="wikitable" border="1"
   
|-
 
|-
!Name
+
|  0x20
!Description
+
|  0x4
!Encoding
+
|  Offset (relative to DVLP start) to filename symbol table
 
|-
 
|-
|DT3
+
| 0x24
|Dot product vec3*vec3
+
| 0x4
|0000 01DD DDDD ??AA AAAA BBBB BBXX XXXX
+
| Size of filename symbol table
|-
  −
|DT4
  −
|Dot product vec4*vec4
  −
|0000 10DD DDDD ??AA AAAA BBBB BBXX XXXX
  −
|-
  −
|MOV
  −
|Move register
  −
|0010 01DD DDDD ??AA AAAA 0000 00XX XXXX
  −
|-
  −
|CMP
  −
|Set condition codes
  −
|1011 1?DD DDDD ??AA AAAA ???? ??XX XXXX
  −
|-
  −
|CALL/JMP
  −
|Jump
  −
|1001 J??? ??SS SSSS SSSS SSLL LLLL LLLL
  −
|-
  −
|IF/ELSE
  −
|Enter if-block based on condition codes
  −
|1010 00E? ??SS SSSS SSSS SSLL LLLL LLLL
  −
|-
  −
|END
  −
|Ends a block (?)
  −
|1000 0100 0000 0000 0000 0000 0000 0000
  −
|}
  −
 
  −
=== Fields ===
  −
{| class="wikitable" border="1"
  −
|-
  −
!Name
  −
!Description
  −
|-
  −
|D
  −
|dest register
  −
|-
  −
|A
  −
|opA register
  −
|-
  −
|B
  −
|opB register
  −
|-
  −
|X
  −
|extension id
  −
|-
  −
|S
  −
|absolute offset for code (in words)
  −
|-
  −
|L
  −
|number of instructions to execute
   
|-
 
|-
|J
  −
|JMP or CALL instruction
  −
|-
  −
|E
  −
|IF or ELSE instruction
   
|}
 
|}
   Line 149: Line 92:  
|  0x4
 
|  0x4
 
|  Magic "DVLE"
 
|  Magic "DVLE"
 +
|-
 +
|  0x4
 +
|  0x2
 +
|  Unknown, same value as in DVLP. (Likely a version number)
 
|-
 
|-
 
|  0x6
 
|  0x6
 
|  0x1
 
|  0x1
 
|  Shader type (0x0 = vertex shader, 0x1 = geometry shader; might contain other flags)
 
|  Shader type (0x0 = vertex shader, 0x1 = geometry shader; might contain other flags)
 +
|-
 +
|  0x7
 +
|  0x1
 +
|  true = merge vertex and geometry shader outmaps (geometry shader)
 
|-
 
|-
 
|  0x8
 
|  0x8
 
|  0x4
 
|  0x4
Program's main offset in binary blob (in words)
+
Executable's main offset in binary blob (in words)
 
|-
 
|-
 
|  0xC
 
|  0xC
 
|  0x4
 
|  0x4
Program's endmain offset in binary blob (in words)
+
Executable's program's endmain offset in binary blob (in words)
 +
|-
 +
|  0x10
 +
|  0x2
 +
|  Bitmask of used input registers
 +
|-
 +
|  0x12
 +
|  0x2
 +
|  Bitmask of used output registers
 +
|-
 +
|  0x14
 +
|  0x1
 +
|  Geometry shader type (point = 0x0, variable/subdivide = 0x1, fixed/particle = 0x2)
 +
|-
 +
|  0x15
 +
|  0x1
 +
|  Starting float constant register number for storing the fixed-size primitive vertex array (geometry shader, fixed mode)
 +
|-
 +
|  0x16
 +
|  0x1
 +
|  Number of fully-defined vertices in the variable-size primitive vertex array (geometry shader, variable mode)
 +
|-
 +
|  0x17
 +
|  0x1
 +
|  Number of vertices in the fixed-size primitive vertex array (geometry shader, fixed mode)
 
|-
 
|-
 
|  0x18
 
|  0x18
 
|  0x4
 
|  0x4
|  Offset (relative to DVLE start) to uniform table
+
|  Offset (relative to DVLE start) to constant table
 
|-
 
|-
 
|  0x1C
 
|  0x1C
 
|  0x4
 
|  0x4
|  Number of entries in uniform table (each entry is 0x14-byte long)
+
|  Number of entries in constant table (each entry is 0x14-byte long)
 
|-
 
|-
 
|  0x20
 
|  0x20
Line 188: Line 163:  
|  0x30
 
|  0x30
 
|  0x4
 
|  0x4
|  Offset (relative to DVLE start) to variable (?) table
+
|  Offset (relative to DVLE start) to uniform table
 
|-
 
|-
 
|  0x34
 
|  0x34
 
|  0x4
 
|  0x4
|  Number of entries in variable table (each entry is 0x8-byte long)
+
|  Number of entries in uniform table (each entry is 0x8-byte long)
 
|-
 
|-
 
|  0x38
 
|  0x38
Line 204: Line 179:  
|}
 
|}
   −
Label table entry :
+
=== Label Table Entry ===
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 212: Line 187:  
|-
 
|-
 
|  0x0
 
|  0x0
0x1
+
0x2
 
|  Label ID
 
|  Label ID
 +
|-
 +
|  0x0
 +
|  0x2
 +
|  Unknown (always 1?)
 
|-
 
|-
 
|  0x4
 
|  0x4
Line 221: Line 200:  
|  0x8
 
|  0x8
 
|  0x4
 
|  0x4
?
+
Size of label's location (in words). 0xFFFFFFFF/(uint32_t)-1 if there is no size.
 
|-
 
|-
 
|  0xC
 
|  0xC
Line 229: Line 208:  
|}
 
|}
   −
Uniform table entry :
+
=== Constant Table Entry ===
 +
 
 +
Each executable's constants are stored in a constant table. This information is used by ctrulib's SHDR framework to automatically send those values to the GPU when changing to a given program. An entry is constituted by a header and the constant data, the latter of which uses a format specific to the constant type.
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
!  Offset
 +
!  Size
 +
!  Description
 +
|-
 +
|  0x0
 +
|  0x1
 +
|  Constant type (0=bool, 1=ivec4, 2=vec4)
 +
|-
 +
|  0x2
 +
|  0x1
 +
|  Constant register ID
 +
|}
 +
 
 +
Corresponding constant entry formats:
 +
 
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 235: Line 234:  
!  Size
 
!  Size
 
!  Description
 
!  Description
 +
|-
 +
|  0x0
 +
|  0x1
 +
|  0x0
 
|-
 
|-
 
|  0x2
 
|  0x2
 
|  0x1
 
|  0x1
Uniform ID
+
Boolean constant register ID
 +
|-
 +
|  0x4
 +
|  0x1
 +
|  Value (boolean)
 +
|}
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
!  Offset
 +
!  Size
 +
!  Description
 +
|-
 +
|  0x0
 +
|  0x1
 +
|  0x1
 +
|-
 +
|  0x2
 +
|  0x1
 +
|  Integer constant register ID
 +
|-
 +
|  0x4
 +
|  0x1
 +
|  x (u8)
 +
|-
 +
|  0x5
 +
|  0x1
 +
|  y (u8)
 +
|-
 +
|  0x6
 +
|  0x1
 +
|  z (u8)
 +
|-
 +
|  0x7
 +
|  0x1
 +
|  w (u8)
 +
|}
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
!  Offset
 +
!  Size
 +
!  Description
 +
|-
 +
|  0x0
 +
|  0x1
 +
|  0x2
 +
|-
 +
|  0x2
 +
|  0x1
 +
|  floating-point constant register ID
 
|-
 
|-
 
|  0x4
 
|  0x4
Line 257: Line 310:  
|}
 
|}
   −
Output register table entry :
+
=== Output Table Entry ===
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 265: Line 318:  
|-
 
|-
 
|  0x0
 
|  0x0
0x4
+
0x2
Descriptor ?
+
Output type (see table below)
 +
|-
 +
|  0x2
 +
|  0x2
 +
|  Register ID
 
|-
 
|-
 
|  0x4
 
|  0x4
 
|  0x2
 
|  0x2
|  Output type (see table below)
+
|  Output attribute component mask (e.g. 5=xz)
 
|-
 
|-
 
|  0x6
 
|  0x6
 
|  0x2
 
|  0x2
|  (Register ID) >> 1
+
Unknown (Consistently the same number throughout the DVLE, may vary between DVLEs?)
 +
|-
 
|}
 
|}
   −
Output types (vertex shader) :
+
Output types :
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
ID
+
Type
 
!  Description
 
!  Description
 
|-
 
|-
Line 287: Line 345:  
|-
 
|-
 
|  0x1
 
|  0x1
?
+
result.normalquat
 
|-
 
|-
 
|  0x2
 
|  0x2
Line 296: Line 354:  
|-
 
|-
 
|  0x4
 
|  0x4
?
+
result.texcoord0w
 
|-
 
|-
 
|  0x5
 
|  0x5
Line 308: Line 366:  
|-
 
|-
 
|  0x8
 
|  0x8
?
+
result.view
 
|}
 
|}
   −
Variable table entry :
+
=== Uniform Table Entry ===
 +
 
 +
Keep in mind that the usage of the term "Uniform" here is used as [https://developer.download.nvidia.com/CgTutorial/cg_tutorial_chapter03.html defined by Nvidia] (variable who obtains its initial value from an external environment) and not as defined by RenderMan/GLSL (variables whose values are constant over a shaded surface).
 +
 
 +
The uniform table contains a list of all registers whose initial values are derived by an external source along with their layout and associated symbol.
 +
 
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 324: Line 387:  
|  0x4
 
|  0x4
 
|  0x2
 
|  0x2
Variable start register
+
Register index of the start of the uniform
 
|-
 
|-
 
|  0x6
 
|  0x6
 
|  0x2
 
|  0x2
Variable end register
+
Register index of the end of the uniform (equal to start register for non-arrays)
 +
|-
 +
|}
 +
 
 +
The register indices refer to a unified register space for non-output registers. The mapping of register index values to registers is the following:
 +
{| class="wikitable" border="1"
 +
|-
 +
!  Values
 +
!  Registers
 +
|-
 +
|  0x00-0x0F
 +
|  v0-v15
 +
|-
 +
|  0x10-0x6F
 +
|  c0-c95
 +
|-
 +
|  0x70-0x73
 +
|  i0-i3
 +
|-
 +
|  0x78-0x87
 +
|  b0-b15
 +
|-
 +
|}
 +
 
 +
== DVOJ ==
 +
There is another file format for shaders, which starts with the string "DVOJ". This format seems to be used for unlinked shader objects. It seems likely that one or multiple DVOJs can be linked to a DVLB file, similarly to the C compilation model.
 +
 
 +
Structurally, a DVOJ header captures all information there is about a single shader instance. It uses the same fields like the DVLB, DVLP, and DVLE structures, but also stores two unknown blocks of data. It seems that the entry point of a DVOJ is always the first shader instruction.
 +
 
 +
All offsets in the following table are given relative to the DVOJ start.
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
!  Offset
 +
!  Size
 +
!  Description
 +
|-
 +
|  0x00
 +
|  0x4
 +
|  Magic "DVOJ"
 +
|-
 +
|  0x04
 +
|  0x4
 +
|  Unknown. Seems to be related to the DVLE shader type.
 +
|-
 +
|  0x08
 +
|  0x4
 +
|  Unknown.
 +
|-
 +
|  0x0C
 +
|  0x4
 +
|  Padding? (usually 0xFFFFFFFF)
 +
|-
 +
|  0x10
 +
|  0x4
 +
|  Offset to constant table
 +
|-
 +
|  0x14
 +
|  0x4
 +
|  Number of entries in constant table (each entry is 0x14-byte long)
 +
|-
 +
|  0x18
 +
|  0x4
 +
|  Offset to label table
 +
|-
 +
|  0x1C
 +
|  0x4
 +
|  Number of entries in label table (each entry is 0x10-byte long)
 +
|-
 +
|  0x20
 +
|  0x4
 +
|  Offset to the compiled shader binary blob
 +
|-
 +
|  0x24
 +
|  0x4
 +
|  Size of compiled shader binary blob, in words
 +
|-
 +
|  0x28
 +
|  0x4
 +
|  Offset (relative to DVLP start) to shader instruction extension table
 +
|-
 +
|  0x2C
 +
|  0x4
 +
|  Number of shader instruction extension table entries (each entry is 8-byte long)
 +
|-
 +
|  0x30
 +
|  0x4
 +
|  Offset to unknown block 1
 +
|-
 +
|  0x34
 +
|  0x4
 +
|  Number of items in unknown block 1 (each item is 8-byte long). This seems to be equal to the total number of instructions.
 +
|-
 +
|  0x38
 +
|  0x4
 +
|  Offset to unknown block 2
 +
|-
 +
|  0x3C
 +
|  0x4
 +
|  Number of items in unknown block 2 (each item is 12-byte long). This seems to be equal to the number of instructions taking arguments (i.e. excluding NOP, END, ...)
 +
|-
 +
|  0x40
 +
|  0x4
 +
|  Offset to output register table
 +
|-
 +
|  0x44
 +
|  0x4
 +
|  Number of entries in output register table (each entry is 0x8-byte long)
 +
|-
 +
|  0x48
 +
|  0x4
 +
|  Offset to uniform table
 +
|-
 +
|  0x4C
 +
|  0x4
 +
|  Number of entries in uniform table (each entry is 0x8-byte long)
 +
|-
 +
|  0x50
 +
|  0x4
 +
|  Offset to symbol table
 +
|-
 +
|  0x54
 +
|  0x4
 +
|  Size of symbol table (in bytes)
 
|-
 
|-
 
|}
 
|}
   −
Each DVLE is associated to an individual shader shader program contained in the binary blob. A single shader binary blob may contain multiple shader programs of the same kind.
     −
Each program's constants are stored as vec4 in a uniform table. These are sent over to the GPU when changing to a give program.
+
=== Unknown Block 1 Item ===
 +
A wild guess is that this denotes shader source line information. Take the information with a grain of salt, though, since it hasn't been backed by any empirical data so far.
 +
 
 +
The index N of the item within Unknown Block 1 corresponds to the Nth instruction in the shader binary.
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
!  Offset
 +
!  Size
 +
!  Description
 +
|-
 +
|  0x0
 +
|  0x4
 +
|  Byte offset within symbol table pointing to a source shader filename.
 +
|-
 +
|  0x4
 +
|  0x4
 +
|  Line number of the corresponding shader instruction within the shader source code.
 +
|-
 +
|}
 +
 
 +
=== Unknown Block 2 Item ===
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
!  Offset
 +
!  Size
 +
!  Description
 +
|-
 +
|  0x0
 +
|  0x4
 +
|  This seems to be an index of a shader instruction. All non-nullary instructions seem to be referenced exactly once.
 +
|-
 +
|  0x4
 +
|  0x4
 +
 +
|-
 +
|  0x8
 +
|  0x4
 +
 +
|-
 +
|}
35

edits

Navigation menu