This note is based on Microsoft DirectX 9 Programmable Graphics Pipeline. If you are not familiar with the English language, you can refer to this note. If not specified, you can refer to this document in this series!
Different registers have different functions:
The input register reads data from the vertex buffer.
Constant registers provide various constants required for ALU Calculation
Temporary registers store temporary variables used by shader computing
The output register stores the calculation result of the shader program.
Shader program Layout
An assembly coloring program contains different types of commands. Just like other programming languages, some commands must appear before other commands. Commands can be divided into the following parts:
♢Version Declaration
♢Note
♢Constant
♢Input register Declaration
♢Operation instructions
The following is an example:
The first instruction in each coloring program must be a version declaration, which indicates the code of the corresponding version to be compiled by the coloring program. This example code can be run on hardware supporting vs_1_1.
Annotations can appear anywhere in the shader program. They are marked with attention, similar to the C language.
Constants can be set in the program or declared in the shader Code. These constants are read by the shader in read-only mode. Each register can store four values.
The input register must be associated with semantics before use, because the shader must correspond to the data in the input vertex buffer. In this example, the location coordinates of v0 and the buffer are bound together.
Once constants and input registers are declared, you can use operation commands to write the shader program.
Bytes ----------------------------------------------------------------------------------------
Register
Different registers have different purposes. the input register is responsible for providing data to ALU. the runtime data stream is transmitted from the vertex buffer into the input register, and the input register is providing the data to ALU. the vertex shader result is written into the output register, and then the result is put back into the rendering pipeline for processing.
Other input registers include constant registers and temporary registers that store temporary values. The following table lists the types of input registers:
Input register table. (ps: n/a indicates that this version is unavailable)
A0: an indirect register that can be used as an index to address constant registers. In vs_1_1, only a0.x can be used. In later versions, all components can be accessed.
AL: an integer counter that controls the maximum number of cycles.
B #: Compare conditions for accommodating callnz commands.
C #: Floating Point General registers.
I #: integer constant register, controlling loop commands
P0: predicate register, which provides the function of throttling by each component: that is, the specified operation is performed only when the component value is true.
R #: a temporary register used to access the temporary computation results. Unlike a constant register, this register is readable and writable, and a constant register is read-only.
S #: Sampling register. When the texture is sampled, the color of the grain is written into the sampling register.
V #: input register. The vertex buffer transmits data to the pre-declared input register in the vertex shder.
Number of registers that can be read by a single command at the same time. For details, refer to the SDK. An error message is returned if the limit is exceeded.
All devices use caps to specify their feature sets. each type of caps is included in the D3DCAPS9 structure. the simple way to test caps is to use the CMyD3DApplication: ConfirmDevices method, which is included in the SDK example.
Output register type (ps: * indicates an integer between 0 and number of resources)
In all versions earlier than vs_3_0, oD0 contains the diffuse reflection value, and oD1 contains the mirror reflection value. The oPos value must be written.
After vs_3_0 and above, the output registers are integrated into 12 o # registers. each o # register can be used as a parameter for pixel shader interpolation. in addition, the output register must be declared now. this statement binds the semantics to the register and binds the output of the vertex shader to the input of the pixel shader.
Of all 12 4-component registers, one must be declared as a Location Register.
All registers must be declared before use.
In the early shader Model, only the c # register can be indexed. In vs_3_0, v # And 0 # can also be indexed using a0.
Bytes ----------------------------------------------------------------------------------------
Operation instructions
The command determines when the data is transferred from the Register to ALU, and the operation performed by ALU on the data. There are the following types of operation commands in the Set:
■ Preset commands
■ Arithmetic commands
■ Macro operation commands
■ Texture command
■ Flow control commands
The preset command is used to declare the shader program version and constant. arithmetic commands provide mathematical operations. macro commands provide advanced functions, such as cross multiplication and linear interpolation. the texture command is used to sample textures, and the flow control command controls which commands are executed.
Each version of shder supports a maximum number of command slots. if this number is exceeded, the command will become invalid. as the version increases, the maximum number of instruction slots is constantly increasing. the following table lists the maximum number of commands in each command slot:
Vs_1_1 128
Vs_2_0 256
Vs _2_x 256
Vs_2_sw Unlimited
Vs_3_0 512
Vs_3_sw Unlimited
Preset commands: used for initialization, such as declaring the shader version, defining constants, and declaring registers.
Arithmetic commands: Provides mathematical operations. For more information, see the SDK.
Macro commands: some arithmetic commands are combined and optimized accordingly. For details, see the SDK.
Texture command: 3.0 things, temporarily unavailable.
Traffic control command: Provides branch computing. For details, refer to the SDK.
Bytes ----------------------------------------------------------------------------------------
Modifier extension:
The modifier does not occupy the instruction slot.
The Operation Command modifier adjusts the operations on data. _ sat sets the value of the data value folder to 0 to 1 before writing data to the target register. The following _ pp modifier indicates that low-precision commands are allowed. however, some write commands do not support _ sat modifiers, such as frc and sincos, as well as texture commands, and the target register cannot be o #.
The target register modifier affects how the result is written into the target register. specifically, a write mask controls the register components written by the target. in addition, the write mask must be arranged in the order of components, no matter how many components need to be written. for example. rga and. xw is a valid mask. no mask is used to indicate that all four components are written.
The source register modifier modifies data before the data is copied from the source register to ALU. (the value in the source register is not changed .) the modifier before the source register has negative number, absolute value, and negative value after the absolute value. There is only obfuscation after the source register.
■ Negative modifier: If you need an inverse number of source data, you only need to add "-" to the source register.
■ Absolute value modifier: ensure that the result is the absolute value of a number.
■ Negative value after absolute value: obtain absolute value first and then take negative value for it.
■ Obfuscation: controls the Read Source register components. obfuscation does not affect the data in the source register, because a source register using obfuscation is copied to a temporary region before the command operation.
Bytes ----------------------------------------------------------------------------------------
Differences between different vertices shader versions:
What version of vertex shder should you use? Do you need static traffic control? Do you want to support texture sampling? Maybe you are tired of writing low-level functions and want to use more advanced macro commands to reduce workload and improve performance. generally, use a later version of shader to improve performance and convert your shader into a later version of shader. of course, your hardware must be supported.
DirectX9 supports the following versions:
Vs_1_1
Vs_2_0, vs_2_x, vs_2_sw
Vs_3_0, vs_3_sw
Vs_1_1 is the earliest version. it contains errors of the basic register type: input, output, constant, temporary, and an addressing register. the operation instruction set contains all basic arithmetic commands and almost half of macro commands. traffic control is not supported.
Vs_2_0 adds some new arithmetic commands such as abs, crs, and some macro operation commands such as lrp, nrm, pow, sgn, sincos. however, the biggest improvement is the support for static flow control commands, such as if-else-endif, call, loop, rep. for the first time, shader can use flow control to determine the running branch. boolean and integer registers are added to support this function.
Vs_2_x introduces dynamic stream control, such as break_comp, break_pred, if_comp, if_pred. assertions are also executed by the introduced command.
Vs_2_sw is a software-only shader, which is very slow and is not described too much.
Vs_3_0, the output register is simplified to one type register: o #. therefore, the output register must declare the corresponding semantics to connect the pixel shader. vs_3_0 also supports dynamic Stream Control of assertion, but does not need to set caps flag like _ 2_0. vs_3_0 also supports texture sampling and control of vertex stream sequence, so that users can still have control capability after stream reset.
Vs_3_sw is the _ 3_0 software version, which is very slow.