Compute Shader 语法及函数 Reference for HLSL_hlsl compute shader-程序员宅基地

技术标签: compute shader  游戏引擎  HLSL  Direct3D  

///

变量语法

使用以下语法规则声明 HLSL 变量。

[Storage_Class] [Type_ModifierType Name[Index] [: Semantic] [: Packoffset] [: Register]; [Annotations] [= Initial_Value]

参数

存储 _班级

可选的存储类修饰符,它们为编译器提示指定变量范围和生存期;可以按任意顺序指定修饰符。

说明
extern 将全局变量标记为着色器的外部输入;这是所有全局变量的默认标记。 不能与 static组合。
nointerpolation 在将顶点着色器的输出传递到像素着色器之前,不要插入它们。
应用于变量的 精确 关键字将限制用于生成通过以下方式分配给该变量的值的任何计算: * 单独的操作保持独立。 例如,mul 和 add 操作可能已融合到 mad 操作中,因此 精确 强制操作保持独立。 相反,你必须显式使用 mad 内部函数。将保留运算的顺序。 其中的指令顺序可能已打乱,以提高性能, 精确 确保编译器按书面顺序保留顺序。 * IEEE 不安全操作受到限制。 在某些情况下,编译器可能使用了无法计算 NaN (不是数字的数字) 并且 INF (无限) 值, 精确 地强制要求遵循 NAN 和 INF 值的 IEEE 要求。 如果没有 确切的优化,则这些优化和数学运算不是 IEEE safe。 * 限定变量 精度 不会使使用可变 精确的操作。 由于 精确 地仅传播到分配给 精确限定变量的值的操作,因此正确地进行所需 的计算可能会比较 复杂,因此,我们建议您将着色器输出 精确 地标记为声明它们的位置,无论是在结构字段上,还是在输出参数上,或在输入函数的返回类型上。通过这种方式控制优化的功能可以禁用可能会影响最终结果的优化,因为累积精度差异差异可能会影响最终结果。 当您希望镶嵌的着色器在多个刀路上维持水紧密的接插,或匹配深度值时,此方法非常有用。示例代码: HLSLmatrix g_mWorldViewProjection;void main(in float3 InPos : Position, out precise float4 OutPos : SV_Position){ // operation is precise because it contributes to the precise parameter OutPos OutPos = mul( float4( InPos, 1.0 ), g_mWorldViewProjection );}
共享 标记用于在效果之间共享的变量;这是对编译器的提示。
groupshared 为计算着色器标记线程组共享内存的变量。 在 D3D10 中,groupshared 存储类的所有变量的最大总大小为16kb,在 D3D11 中,最大大小为32kb。 请参阅示例。
static 标记局部变量,使其初始化一次并在函数调用之间保持。 如果该声明不包含初始值设定项,则将该值设置为零。 标记为 static 的全局变量对应用程序不可见。
uniform 在着色器 ((例如,顶点着色器中的材料颜色) ;默认情况下,全局变量被视为 统一 。
volatile 标记经常更改的变量;这是对编译器的提示。 此存储类修饰符仅适用于局部变量。
[!Note]
HLSL 编译器当前忽略此存储类修饰符。

类型 _ 修饰符

可选的变量类型修饰符。

说明
const 标记着色器无法更改的变量,因此必须在变量声明中对其进行初始化。 全局变量默认视为 const (通过向编译器) 提供/Gec 标志来禁止显示此行为。
行 _ 主 在单个行中标记存储四个组件的变量,以便可以将其存储在单个常量寄存器中。
列 _ 主要 将存储4个组件的变量标记为一个列,以优化矩阵数学。

 备注

如果未指定类型修饰符值,编译器将使用 列 _ 主要 作为默认值。

类别

(DIRECTX HLSL) 的数据类型中列出的任何 HLSL 类型。

名称 [索引]

唯一标识着色器变量的 ASCII 字符串。 若要定义可选数组,请对数组大小使用 索引 ,该大小为正整数 = 1。

语义

可选的参数用法信息,由编译器用来链接着色器输入和输出。 顶点和像素着色器有多个预定义的 语义 。 编译器会忽略语义,除非它们是在全局变量上声明的,或者是传递到着色器的参数。

Packoffset

用于手动包装着色器常量的可选关键字。 请参阅 packoffset (DIRECTX HLSL) 

注册

用于手动将着色器变量分配给特定寄存器的可选关键字。 请参阅 register (DIRECTX HLSL) 

批注 (s)

附加到全局变量的可选元数据(以字符串形式)。 批注由效果框架使用,由 HLSL 忽略;若要查看更详细的语法,请参阅 批注语法

初始值 _

可选初始值 (s) ;值的数目应匹配 类型 中的组件数。 标记为 extern 的每个全局变量都必须使用文本值进行初始化;标记为 static 的每个变量都必须使用常量进行初始化。

未标记为 static 或 extern 的全局变量不会编译到着色器中。 编译器不会自动设置全局变量的默认值,也不能在优化中使用它们。 若要初始化此类型的全局变量,请使用反射来获取其值,然后将该值复制到常量缓冲区。 例如,可以使用 ID3D11ShaderReflection:: GetVariableByName方法获取变量,使用 ID3D11ShaderReflectionVariable:: GetDesc方法获取着色器变量说明,并从 D3D11 _ 着色器 _ 变量 _ DESC结构的 DefaultValue 成员获取初始值。 若要将值复制到常量缓冲区,必须确保使用 CPU 写访问创建缓冲区, (D3D11 _ cpu _ 访问 _ 写入) 。 有关如何创建常量缓冲区的详细信息,请参阅 如何:创建常量缓冲区

你还可以使用 效果框架 自动处理反射并设置初始值。 例如,可以使用 ID3DX11EffectPass:: Apply 方法。

示例

下面是着色器变量声明的几个示例。

float fVar;

float4 color;
float fVar = 3.1f;

int iVar[3];

int iVar[3] = {1,2,3};

uniform float4 position : SV_POSITION; 
const float4 lightDirection = {0,0,1};

组共享

HLSL 使计算着色器的线程可以通过共享内存交换值。 HLSL 提供了关卡基元(如 GroupMemoryBarrierWithGroupSync)等,以确保在着色器中对共享内存进行正确的读写排序,并避免数据争用。

 备注

硬件在 (个 warp 或 wave 正面) 的组中执行线程,有时当只同步属于同一组的线程时,可能会省略关卡同步以提高性能。 但我们强烈反对这种省略原因:

  • 这种情况会导致不可移植的代码,这可能不会在某些硬件上运行,也不能用于通常在较小的组中执行线程的软件 rasterizers。
  • 与使用所有线程关卡相比,使用这种省略可能实现的性能改进会很小。

在 Direct3D 10 中,在写入 groupshared 时不会同步线程,因此,这意味着每个线程都限于数组中的单个位置用于写入。 写入时,使用 SV _ GroupIndex system 值为此数组编制索引,以确保两个线程不会发生冲突。 在读取方面,所有线程都有权访问整个数组进行读取。

struct GSData
{
    float4 Color;
    float Factor;
}

groupshared GSData data[5*5*1];

[numthreads(5,5,1)]
void main( uint index : SV_GroupIndex )
{
    data[index].Color = (float4)0;
    data[index].Factor = 2.0f;
    GroupMemoryBarrierWithGroupSync();
    ...
}

包装

打包其大小足以防止跨越寄存器边界的矢量和标量子组件。 例如,这些都是有效的:

cbuffer MyBuffer
{
    float4 Element1 : packoffset(c0);
    float1 Element2 : packoffset(c1);
    float1 Element3 : packoffset(c1.y);
}

不能混合打包类型。

与 register 关键字一样,packoffset 可以特定于目标。 子组件打包仅适用于 packoffset 关键字,而不适用于 register 关键字。 在 cbuffer 声明中,将忽略 Direct3D 10 目标的 register 关键字,因为它假定为 跨平台兼容性。

打包的元素可能会重叠,编译器不会给出任何错误或警告。 本示例中,Element2 和 Element3 将与 Element1.x 和 Element1.y 重叠。

cbuffer MyBuffer
{
    float4 Element1 : packoffset(c0);
    float1 Element2 : packoffset(c0);
    float1 Element3 : packoffset(c0.y);
}

packoffset

可选的着色器常量打包关键字,它使用以下语法:

:packoffset ( c [ 子组件 ] [ .component ] )

parameters

项目 说明
packoffset 必需的关键字。
C 封装仅适用于 c (c) 寄存器。
[子组件 ] [ .component] 可选子组件和组件。 子component 是一个寄存器号,它是一个整数。 组件的形式为 [ .xyzw ] 。

备注

声明变量类型 时,使用此关键字手动 打包着色器常量

打包常量时,不能混用常量类型。

对于全局常量和统一常量,编译器的行为略有不同:

  • 全局常量。 全局变量作为全局常量添加到编译器$Global cbuffer。 自动打包 (在未使用 packoffset) 声明的元素将显示在最后一个手动打包的变量之后。 打包全局常量时,可以混合使用类型。
  • 统一常量。 在效果框架之外编译着色器时,编译器$Param函数的参数列表中的统一参数添加到一个常量缓冲区。 在效果框架中编译时,统一常量必须解析为全局范围中定义的统一变量。 不能手动偏移统一常量;它们的建议用途仅适用于着色器专用化,其别名返回到全局,而不是作为将应用程序数据传递到着色器的方式。

下面是一些附加示例: 使用着色器模型 4 打包常量

示例

下面是手动打包着色器常量的几个示例。

打包其大小足以防止跨越寄存器边界的矢量和标量子组件。 例如,这些都是有效的:

cbuffer MyBuffer
{
    float4 Element1 : packoffset(c0);
    float1 Element2 : packoffset(c1);
    float1 Element3 : packoffset(c1.y);
}

register

用于将着色器变量分配给特定寄存器的可选关键字,使用以下语法:

参数

注册

Required 关键字。

[着色器 _ 配置文件]

可选的 着色器配置文件,可为着色器目标或只是 ps 或 vs

类型 # [ 子组件]

注册类型、数字和子组件声明。

  • 类型为下列类型之一:

    类型 注册描述
    b 常量缓冲区
    t 纹理和纹理缓冲区
    c 缓冲区偏移量
    s 取样器
    u 无序访问视图
  • # 寄存器号,是整数。

  • 子组件 是可选整数。

备注

可以将一个或多个寄存器赋值添加到相同的变量声明中,用空格分隔。

对于全局范围内的 Direct3D 10 变量, register 关键字的作用与 PACKOFFSET (DirectX HLSL) 关键字相同。

示例

下面是一些示例:

sampler myVar : register( ps_5_0, s );

sampler myVar : register( vs, s[8] );

sampler myVar : register( ps, s[2] ) : register( ps_5_0, s[0] ) : register( vs, s[8] );

HLSL) 的数据类型 

HLSL 支持多种不同的内部数据类型。 此表显示了用来定义着色器变量的类型。

使用此内部类型 定义此着色器变量
Scalar 单组件标量
Vector、 Matrix 多组件向量或矩阵
采样器、 纹理 或 缓冲区 采样器、纹理或缓冲区对象
Struct, 用户定义 自定义结构或 typedef
Array 声明的文本标量表达式包含大多数其他类型
状态对象 State 对象的 HLSL 表示形式

为了帮助你更好地了解如何在 HLSL 中使用矢量和矩阵,你可能需要阅读有关 HLSL 如何使用 每个组件 数学的背景信息。

缓冲区类型

使用以下语法声明缓冲区变量。

parameters

缓冲区

必需的关键字。

类型

标量、矢量和一些矩阵HLSL 类型之一。 可以使用矩阵声明缓冲区变量,只要它适合 4 个 32 位数量。 因此,可以编写 Buffer<float2x2> 。 但是 Buffer<float4x4> 太大,编译器将生成错误。

名字

唯一标识变量名称的 ASCII 字符串。

示例

下面是 PipesGS 示例 中的 PipesGS.fx 文件中 缓冲区声明的示例

Buffer<float4> g_Buffer;

使用 Load HLSL 内部函数的重载版本从缓冲区读取数据,该函数采用一个输入参数 (整数索引) 。 缓冲区的访问就像元素数组一样;因此,此示例读取第二个元素。

float4 bufferData = g_Buffer.Load( 1 );

使用 流输出阶段将数据 输出到缓冲区。

标量类型

HLSL 支持多种标量数据类型:

  • 布尔 值-true 或 false。
  • int -32 位有符号整数。
  • uint -32 位无符号整数。
  • dword -32 位无符号整数。
  •  16 位浮点值。 此数据类型仅用于语言兼容性。 Direct3D 10 着色器目标将所有半个数据类型映射为 float 数据类型。 在统一全局变量上不能使用半种数据类型 (如果需要此功能) 使用/Gec 标志。
  • float -32 位浮点值。
  •  64 位浮点值。 不能使用双精度值作为流的输入和输出。 若要在着色器之间传递双精度值,请将每个  精度值声明为一对 uint 数据类型。 然后,使用 asuint 函数将每个 double 打包到一对 uint s,并使用 asdouble 函数将一对 uint s 重新打包回 double

从 Windows 8 HLSL 开始也支持最小精度标量数据类型。 图形驱动程序可以使用大于或等于其指定位精度的任何精度来实现最小精度标量数据类型。 建议不要依赖依赖于特定基础精度的钳位或包装行为。 例如,图形驱动程序可能会以完整的32位精度对 min16float 值执行算术运算。

  • min16float -最小16位浮点值。
  • min10float -最小10位浮点值。
  • min16int -最小16位有符号整数。
  • min12int -最小12位有符号整数。
  • min16uint -最小16位无符号整数。

有关标量文本的详细信息,请参阅 语法

Direct3D 9 和 Direct3D 10 之间的差异:
在 Direct3D 10 中,以下类型是 float 类型的修饰符。
  • snorm float - IEEE 32 位已签名的浮点,范围为1到1(含)。
  • unorm float - IEEE 32 位无符号的浮点值,范围为0到1(含0到1)。
例如,下面是4个组件的有符号标准化浮点变量声明。

snorm float4 fourComponentIEEEFloat;

字符串类型

HLSL 还支持 字符串 类型,它是 ASCII 字符串。 没有操作或状态接受字符串,但效果可以查询字符串参数和批注。

示例

// top-level variable
float globalShaderVariable; 

// top-level function
void function(
in float4 position: POSITION0 // top-level argument
              )
{
  float localShaderVariable; // local variable
  function2(...)
}

void function2()
{
  ...
}

矢量类型

向量包含一到四个标量组件;向量的每一个分量都必须是同一类型。

TypeNumber 名称

复制

TypeComponents Name

组件

项目 说明
TypeComponents 包含两个部分的单个名称。 第一部分是标 量类型之一 。 第二部分是组件数,必须介于 1 到 4(含)之间。
名字 唯一标识变量名称的 ASCII 字符串。

示例

下面是一些示例:

bool    bVector;   // scalar containing 1 Boolean
int1    iVector = 1;
float3  fVector = { 0.2f, 0.3f, 0.4f };

也可使用此语法声明向量:

vector <Type, Number> VariableName

下面是一些示例:

vector <int,    1> iVector = 1;
vector <double, 4> dVector = { 0.2, 0.3, 0.4, 0.5 };

矩阵类型

矩阵是一种特殊数据类型,包含一到十六个组件。 矩阵的每一个分量都必须具有相同的类型。

TypeComponents 名称

组件

项目 说明
TypeComponents 包含三个部分的单个名称。 第一部分是标 量类型之一 。 第二部分是行数。 第三部分是列数。 行数和列数是介于 1 和 4(含)之间的正整数。
名字 唯一标识变量名称的 ASCII 字符串。

示例

下面是一些示例:

int1x1    iMatrix;   // integer matrix with 1 row,  1 column
int4x1    iMatrix;   // integer matrix with 4 rows, 1 column
int1x4    iMatrix;   // integer matrix with 1 row, 4 columns
double3x3 dMatrix;   // double matrix with 3 rows, 3 columns

float2x2 fMatrix = { 0.0f, 0.1, // row 1
                     2.1f, 2.2f // row 2
                   };   

也可使用此语法声明矩阵:

matrix <Type, Number> VariableName

矩阵类型使用尖括号指定类型、行数和列数。 此示例创建一个浮点矩阵,包含两行和两列。 可以使用任何标量数据类型。

以下是示例:

matrix <float, 2, 2> fMatrix = { 0.0f, 0.1, // row 1
                                 2.1f, 2.2f // row 2
                               };

Per-Component 数学运算

使用 HLSL,可以在算法级别编写着色器。 若要理解语言,你将需要了解如何声明变量和函数、使用内部函数、定义自定义数据类型以及使用语义将着色器参数连接到其他着色器和管道。

了解如何在 HLSL 中创作着色器后,你将需要了解 API 调用,以便能够:编译特定硬件的着色器、初始化着色器常量,并根据需要初始化其他管道状态。

矢量类型

矢量是包含一个和四个组件之间的数据结构。

复制

bool    bVector;   // scalar containing 1 Boolean
bool1   bVector;   // vector containing 1 Boolean
int1    iVector;   // vector containing 1 int
float3  fVector;   // vector containing 3 floats
double4 dVector;   // vector containing 4 doubles

紧跟在数据类型后面的整数是矢量上的组件数。

初始值设定项还可以包含在声明中。

复制

bool    bVector = false;
int1    iVector = 1;
float3  fVector = { 0.2f, 0.3f, 0.4f };
double4 dVector = { 0.2, 0.3, 0.4, 0.5 };

或者,矢量类型可用于进行相同的声明:

复制

vector <bool,   1> bVector = false;
vector <int,    1> iVector = 1;
vector <float,  3> fVector = { 0.2f, 0.3f, 0.4f };
vector <double, 4> dVector = { 0.2, 0.3, 0.4, 0.5 };

矢量类型使用尖括号指定组件的类型和数量。

矢量最多包含四个组件,每个组件都可以使用以下两个命名集之一进行访问:

  • 位置集: x、y、z 和 w
  • 颜色集: r、g、b、a

这些语句都返回第三个组件中的值。

复制

// Given
float4 pos = float4(0,0,2,1);

pos.z    // value is 2
pos.b    // value is 2

命名集可以使用一个或多个组件,但不能混合使用。

复制

// Given
float4 pos = float4(0,0,2,1);
float2 temp;

temp = pos.xy  // valid
temp = pos.rg  // valid

temp = pos.xg  // NOT VALID because the position and color sets were used.

在读取组件时指定一个或多个矢量组件称为 swizzling。 例如:

复制

float4 pos = float4(0,0,2,1);
float2 f_2D;
f_2D = pos.xy;   // read two components 
f_2D = pos.xz;   // read components in any order       
f_2D = pos.zx;

f_2D = pos.xx;   // components can be read more than once
f_2D = pos.yy;

屏蔽控制写入的组件数。

复制

float4 pos = float4(0,0,2,1);
float4 f_4D;
f_4D    = pos;     // write four components          

f_4D.xz = pos.xz;  // write two components        
f_4D.zx = pos.xz;  // change the write order

f_4D.xzyw = pos.w; // write one component to more than one component
f_4D.wzyx = pos;

不能将分配多次写入同一组件。 因此,此语句的左侧无效:

复制

f_4D.xx = pos.xy;   // cannot write to the same destination components 

而且,组件名称空间不能混合。 这是无效的组件写入:

复制

f_4D.xg = pos.rgrg;    // invalid write: cannot mix component name spaces 

以标量形式访问向量将访问向量的第一个组件。 下面两个语句是等效的。

复制

f_4D.a = pos * 5.0f;
f_4D.a = pos.r * 5.0f;

矩阵类型

矩阵是一种数据结构,其中包含数据的行和列。 数据可以是任何标量数据类型,但矩阵的每个元素都是相同的数据类型。 使用追加到数据类型的逐列字符串指定行数和列数。

int1x1    iMatrix;   // integer matrix with 1 row,  1 column
int2x1    iMatrix;   // integer matrix with 2 rows, 1 column
...
int4x1    iMatrix;   // integer matrix with 4 rows, 1 column
...
int1x4    iMatrix;   // integer matrix with 1 row, 4 columns
double1x1 dMatrix;   // double matrix with 1 row,  1 column
double2x2 dMatrix;   // double matrix with 2 rows, 2 columns
double3x3 dMatrix;   // double matrix with 3 rows, 3 columns
double4x4 dMatrix;   // double matrix with 4 rows, 4 columns

最大行数或列数为 4;最小数目为1。

在声明矩阵时可以对其进行初始化:

float2x2 fMatrix = { 0.0f, 0.1, // row 1
                     2.1f, 2.2f // row 2
                   };   

也可以使用矩阵类型进行相同的声明:

matrix <float, 2, 2> fMatrix = { 0.0f, 0.1, // row 1
                                 2.1f, 2.2f // row 2
                               };

矩阵类型使用尖括号来指定类型、行数和列数。 此示例创建一个具有两行和两列的浮点矩阵。 可以使用任意标量数据类型。

此声明定义一个浮点值矩阵 (32 位浮点数) ,其中包含两个行和三个列:

matrix <float, 2, 3> fFloatMatrix;

矩阵包含按行和列组织的值,这些值可使用结构运算符 "." 进行访问,后跟以下两个命名集之一:

  • 从零开始的行列位置:
    • _m00、 _ m01、 _ m02、 _ m03
    • _m10、 _ m11、 _ m12、 _ m13
    • _m20、 _ m21、 _ m22、 _ m23
    • _m30、 _ m31、 _ m32-16ms、 _ m33
  • 从1开始的行列位置:
    • _11、 _ 12、 _ 13、 _ 14
    • _21、 _ 22、 _ 23、 _ 24
    • _31、 _ 32、 _ 33、 _ 34
    • _41、 _ 42、 _ 43、 _ 44

每个命名集均以下划线开头,后跟行号和列号。 从零开始的约定还在行号和列号之前包含字母 "m"。 下面的示例使用两个命名集来访问矩阵:

// given
float2x2 fMatrix = { 1.0f, 1.1f, // row 1
                     2.0f, 2.1f  // row 2
                   }; 

float f_1D;
f_1D = matrix._m00; // read the value in row 1, column 1: 1.0
f_1D = matrix._m11; // read the value in row 2, column 2: 2.1

f_1D = matrix._11;  // read the value in row 1, column 1: 1.0
f_1D = matrix._22;  // read the value in row 2, column 2: 2.1

与矢量一样,命名集可以使用命名集中的一个或多个组件。

// Given
float2x2 fMatrix = { 1.0f, 1.1f, // row 1
                     2.0f, 2.1f  // row 2
                   };
float2 temp;

temp = fMatrix._m00_m11 // valid
temp = fMatrix._m11_m00 // valid
temp = fMatrix._11_22   // valid
temp = fMatrix._22_11   // valid

还可以通过使用数组访问表示法(一组从零开始的索引)来访问矩阵。 每个索引都在方括号内。 使用以下索引访问4x4 矩阵:

  • [0 ] [ 0 ] , [ 0 ] [ 1 ] , [ 0 ] [ 2 ] , [ 0 ] [ 3]
  • [1 ] [ 0 ] , [ 1 ] [ 1 ] , [ 1 ] [ 2 ] , [ 1 ] [ 3]
  • [2 ] [ 0 ] , [ 2 ] [ 1 ] , [ 2 ] [ 2 ] , [ 2 ] [ 3]
  • [3 ] [ 0 ] 、 [ 3 ] [ 1 ] 、 [ 3 ] [ 2 ] 、 [ 3 ] [ 3]

下面是一个访问矩阵的示例:

float2x2 fMatrix = { 1.0f, 1.1f, // row 1
                     2.0f, 2.1f  // row 2
                   };
float temp;

temp = fMatrix[0][0] // single component read
temp = fMatrix[0][1] // single component read

请注意,结构运算符 "." 不用于访问数组。 数组访问符号不能使用 swizzling 读取多个组件。

float2 temp;
temp = fMatrix[0][0]_[0][1] // invalid, cannot read two components

但是,数组访问可以读取多组件向量。

float2 temp;
float2x2 fMatrix;
temp = fMatrix[0] // read the first row

与矢量一样,读取多个矩阵组件称为 swizzling。 如果只使用一个命名空间,则可以分配多个组件。 这些都是有效的分配:

// Given these variables
float4x4 worldMatrix = float4( {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} );
float4x4 tempMatrix;

tempMatrix._m00_m11 = worldMatrix._m00_m11; // multiple components
tempMatrix._m00_m11 = worldMatrix.m13_m23;

tempMatrix._11_22_33 = worldMatrix._11_22_33; // any order on swizzles
tempMatrix._11_22_33 = worldMatrix._24_23_22;

屏蔽控制写入的组件数。

// Given
float4x4 worldMatrix = float4( {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} );
float4x4 tempMatrix;

tempMatrix._m00_m11 = worldMatrix._m00_m11; // write two components
tempMatrix._m23_m00 = worldMatrix._m00_m11;

不能将分配多次写入同一组件。 因此,此语句的左侧无效:

// cannot write to the same component more than once
tempMatrix._m00_m00 = worldMatrix._m00_m11;

而且,组件名称空间不能混合。 这是无效的组件写入:

// Invalid use of same component on left side
tempMatrix._11_m23 = worldMatrix._11_22; 

矩阵排序

默认情况下,统一参数的矩阵封装顺序设置为列-主。 这意味着矩阵的每一列都存储在单个常数寄存器中。 另一方面,行-主矩阵会将矩阵的每一行打包到一个常数寄存器中。 可以通过 # pragmapack _ matrix 指令或 行 _ 主要 关键字或 列 _ 主要 关键字更改矩阵包装。

在着色器运行之前,矩阵中的数据将加载到着色器常数寄存器中。 对于矩阵数据的读取方式有两种选择:按行主顺序或按列主顺序排列。 列优先顺序意味着每个矩阵列都将存储在单个常量寄存器中,行优先顺序意味着矩阵的每一行都将存储在单个常量寄存器中。 对于矩阵使用的常量寄存器数量,这是一个重要的考虑因素。

行主矩阵和列主矩阵排序确定矩阵组件从着色器输入中读取的顺序。 将数据写入常量寄存器后,矩阵顺序不会影响数据在着色器代码中的使用方式或访问方式。 此外,在着色器正文中声明的矩阵不会打包到常数寄存器中。 行主和列主要的封装顺序对构造函数的封装顺序没有影响 (始终遵循行优先顺序) 。

矩阵中数据的顺序可以在编译时声明,或者编译器会在运行时对数据进行排序,以便最有效地使用。

示例

HLSL 使用两种特殊类型,矢量类型和矩阵类型使编程2D 和3D 图形更容易。 其中每个类型都包含多个组件;一个矢量最多包含四个组件,一个矩阵最多包含16个组件。 当在标准 HLSL 公式中使用向量和矩阵时,执行的数学运算适用于每个组件。 例如,HLSL 实现了这一乘法:

float4 v = a*b;

四个分量相乘。 结果为四个标量:

float4 v = a*b;

v.x = a.x*b.x;
v.y = a.y*b.y;
v.z = a.z*b.z;
v.w = a.w*b.w;

这是四个祖,其中每个结果存储在 v 的单独组件中。 这称为四分量乘法。 HLSL 使用组件数学,使编写着色器的效率非常高。

这与乘法非常不同,后者通常实现为点积,这会生成单个标量:

v = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;

矩阵还在 HLSL 中使用每个组件的操作:

float3x3 mat1,mat2;
...
float3x3 mat3 = mat1*mat2;

结果是两个矩阵的每个分量相乘 (相对于标准3x3 矩阵相乘) 。 每个组件的矩阵乘以会产生以下第一项:

mat3.m00 = mat1.m00 * mat2._m00;

这不同于3x3 矩阵乘法,这将产生以下第一项:

// First component of a four-component matrix multiply
mat.m00 = mat1._m00 * mat2._m00 + 
          mat1._m01 * mat2._m10 + 
          mat1._m02 * mat2._m20 + 
          mat1._m03 * mat2._m30;

乘法内部函数的重载版本是指一个操作数为向量,另一个操作数是矩阵。 例如:矢量 * 向量、矢量 * 矩阵、矩阵 * 向量和矩阵 * 矩阵。 例如:

float4x3 World;

float4 main(float4 pos : SV_POSITION) : SV_POSITION
{
    float4 val;
    val.xyz = mul(pos,World);
    val.w = 0;

    return val;
}   

产生与相同的结果:

float4x3 World;

float4 main(float4 pos : SV_POSITION) : SV_POSITION
{
    float4 val;
    val.xyz = (float3) mul((float1x4)pos,World);
    val.w = 0;

    return val;
}   

此示例使用 (float1x4) cast 将 pos 向量转换为列向量。 通过强制转换来更改向量,或交换提供给相乘的参数的顺序等效于转换矩阵。

自动强制转换将导致乘法和点内部函数返回相同的结果,如下所示:

{
  float4 val;
  return mul(val,val);
}

相乘的这一结果是一个 1x4 * 4x1 = 1x1 向量。 这等效于点积:

{
  float4 val;
  return dot(val,val);
}

这会返回单个标量值。

采样器类型

使用以下语法声明采样器状态以及取样器比较状态。

Direct3D 9 和 Direct3D 10 及更高版本之间的差异:
下面是 Direct3D 9 中示例的语法。
采样器名称 = SamplerType{纹理 = <texture_variable > ; [state_name = state_value;] ... };

Direct3D 10 和更高版本中采样器的语法略有不同,以支持纹理对象和采样器数组。

SamplerType Name [Index]{[state_name = state_value;] ... };

parameters

采样

仅限 Direct3D 9。 Required 关键字。

路径名

唯一标识采样器变量名的 ASCII 字符串。

[编入]

仅限 Direct3D 10 和更高版本。 可选数组大小;大于或等于1的正整数。

SamplerType

[在 ] 采样器类型中,这是以下类型之一: 采样 器、 sampler1D、 sampler2D、 sampler3D、 samplerCUBE、 采样器 _ 状态、 SamplerState

Direct3D 9 和 Direct3D 10 及更高版本之间的差异:

  • Direct3D 10 和更高版本支持另一种采样器类型: SamplerComparisonState

纹理 = <纹理 _ 变量>;

仅限 Direct3D 9。 纹理变量。 左侧需要 " 纹理 " 关键字;变量名称在尖括号中的表达式的右侧。

状态 _ 名称 = 状态值 _

[在 ] 可选状态 (s) 中分配。 赋值语句的左侧是一个状态名称,右侧是状态值。 所有状态分配都必须出现在语句块中 () 的大括号中。 每个语句用分号分隔。 下表列出了可能的状态名称。

// sampler state
AddressU
AddressV
AddressW
BorderColor
Filter
MaxAnisotropy
MaxLOD
MinLOD
MipLODBias

// sampler-comparison state
ComparisonFunc

每个表达式的右侧是分配给每个状态的值。 请参阅 D3D11 _ 采样器 _ DESC 结构,了解 Direct3D 11 的可能状态值。 状态名称与结构成员之间存在1到1之间的关系。 请参阅以下示例。

备注

实现效果时,采样器状态是您可能需要在管道中设置以呈现的几种状态之一。 有关可以在效果中设置的所有可能状态的列表,请参阅:

示例

Direct3D 9 和 Direct3D 10 之间的差异:
下面是 BasicHLSL 示例中的 Direct3D 9 采样器的部分示例。

sampler MeshTextureSampler = 
sampler_state
{
    Texture = <g_MeshTexture>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};

下面是 BasicHLSL10 示例中的 Direct3D 10 采样器的部分示例。

SamplerState MeshTextureSampler
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

下面是声明采样器比较状态并在 Direct3D 10 中调用比较示例的部分示例。

SamplerComparisonState ShadowSampler
{
   // sampler state
   Filter = COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
   AddressU = MIRROR;
   AddressV = MIRROR;

   // sampler comparison state
   ComparisonFunc = LESS;
};
        
float3 vModProjUV;
  ...
float fShadow = g_ShadowMap.SampleCmpLevelZero( ShadowSampler, vModProjUV.xy, vModProjUV.z);

着色器类型

在效果中将着色器变量声明为从 Direct3D 9 更改为 Direct3D 10 的语法。

Direct3D 10 的着色器类型

使用着色器类型语法在 Direct3D 10) 中声明 (的着色器变量:

SetPixelShader 编译 ( ShaderTarget,ShaderFunction ) ; SetGeometryShader 编译 ( ShaderTarget,ShaderFunction ) ; SetVertexShader 编译 ( ShaderTarget,ShaderFunction ) ;

parameters

项目 说明
SetXXXShader 创建着色器对象的 Direct3D API 调用。 可以是: SetPixelShader 或 SetGeometryShader 或 SetVertexShader
ShaderTarget 要对其进行编译的着色器模型。 这适用于任何目标,包括所有 Direct3D 9 目标以及 着色器模型 4 目标: vs _ 4 _ 0、gs _ 4 _ 0 和 ps _ 4 _ 0。
ShaderFunction 一个 ASCII 字符串,其中包含着色器入口点函数的名称;这是在调用着色器时开始执行的函数。 ( ... ) 表示着色器参数;它们是传递给着色器创建 API 的相同参数: VSSetShader 或 GSSetShader 或 PSSetShader

示例

下面是一个示例,该示例创建为特定着色器模型编译的顶点着色器和像素着色器对象。 在 Direct3D 10 示例中,没有几何着色器,因此指针设置为 NULL

// Direct3D 10
technique10 Render
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
    }
}

Direct3D 9 的着色器类型

使用着色器类型语法在 Direct3D 9) (中声明着色器变量:

PixelShader = Compile ShaderTarget ShaderFunction ( ) ;VertexShader = Compile ShaderTarget ShaderFunction ( ) ;

parameters

项目 说明
XXXShader 表示已编译的着色器的着色器变量。 可以是: PixelShader 或 VertexShader
ShaderTarget 要对其进行编译的 着色器模型 ;取决于着色器变量的类型。
ShaderFunction ( ... ) 一个 ASCII 字符串,其中包含着色器入口点函数的名称;这是在调用着色器时开始执行的函数。 ( ... ) 表示着色器参数;它们是传递给着色器创建 API 的相同参数: SetVertexShader 或 SetPixelShader

示例

下面是针对特定着色器模型编译的顶点着色器和像素着色器对象的示例。

// Direct3D 9
technique RenderSceneWithTexture1Light
{
    pass P0
    {          
        VertexShader = compile vs_2_0 RenderSceneVS( 1, true, true );
        PixelShader  = compile ps_2_0 RenderScenePS( true );
    }
}

纹理类型

使用以下语法声明纹理变量。

类型名称;

parameters

项目 说明
类别 以下类型之一:纹理 (非类型化的,以便向后兼容性) 、Texture1D、Texture1DArray、Texture2D、Texture2DArray、Texture3D、TextureCube。 元素大小必须适合 4 32 位的数量。
路径名 唯一标识变量名称的 ASCII 字符串。

备注

使用纹理有三个部分。

  1. 声明纹理变量。 这是通过上面所示的语法来完成的。 例如,它们是有效的声明。

    texture g_MeshTexture;
    

    - 或 -

    Texture2D g_MeshTexture;
    
  2. 声明和初始化采样器对象。 这是通过 Direct3D 9 和 Direct3D 10 中略有不同的语法来完成的。 有关取样器对象语法的详细信息,请参阅 (DIRECTX HLSL) 的采样器类型 

  3. 在着色器中调用纹理函数。

Direct3D 9 和 Direct3D 10 之间的差异:

Direct3D 9 使用 内部纹理函数 执行纹理操作。 此示例来自 BasicHLSL 示例 ,并使用 tex2D (s、t) (DirectX HLSL) 来执行纹理采样。

Output.RGBColor = tex2D(MeshTextureSampler, In.TextureUV) * In.Diffuse;

Direct3D 10 改用 模板化纹理对象 。 下面是等效纹理操作的示例。

Output.RGBColor = g_MeshTexture.Sample(MeshTextureSampler, In.TextureUV) * In.Diffuse;

结构类型

使用以下语法通过 HLSL 声明结构。

结构名称 {  [ InterpolationModifier ] Type [ R x C ] MemberName; ... };

参数

名字

唯一标识结构名称的 ASCII 字符串。

[InterpolationModifier]

指定内插类型的可选修饰符。 有关详细信息,请参阅“备注”。

类型 [R x C]

具有可选行的成员类型 (R) x 列 (C) 数组大小。 结构至少包含一个元素;如果它包含多个元素,则这些元素都是同一类型。 行数和列数是介于 1 到 4(含)之间的无符号整数。

MemberName

唯一标识成员名称的 ASCII 字符串。

备注

可以在任何结构成员或像素着色器函数的参数上指定内插修饰符。 如果修饰符同时出现在两处,则 (着色器参数修饰符) 将覆盖结构修饰符 (内修饰符) 。

编译着色器或效果时,着色器编译器根据 HLSL打包规则 打包结构成员。

着色器模型 4 中引入的内插修饰符

用于像素着色器输入的顶点着色器输出将线性内插,以在光栅化期间获取每像素值。 若要设置内插方法,请使用着色器模型 4 或更高版本中支持的任何以下值。 对于不用作像素着色器输入的任何顶点着色器输出,将忽略 修饰符。

内插修饰符 说明
线性 在着色器输入之间内插; 如果 未指定内插修饰符,则 linear 是默认值。
质心 在像素覆盖区域中的某一位置的样本之间内插 (这可能需要从像素中心位置推断) 。 如果像素被部分覆盖,质心采样可能会改进抗锯 (即使像素中心未覆盖) 。 质心修饰 符必须与线性修饰符或 noperspective 修饰符结合使用。
nointerpolation 不要内插 。
noperspective 请勿在内插期间执行透视更正。 noperspective 修饰符可以与 质心修饰符 结合使用。
样品 在着色器模型 4.1 及更高版本中可用 在样本位置(而不是像素中心)内插。 这将导致像素着色器按样本执行,而不是按像素执行。 导致按示例执行的另一种方式是使用语义 SV _ SampleIndex输入,该输入指示当前示例。 只有具有指定示例 (或输入 SV SampleIndex) 的输入在像素中的着色器调用之间有所不同,而未指定修饰符 (的其他输入(例如,如果混合使用不同输入的修饰符) 则仍在像素中心内 _ 插)。 像素着色器调用和深度/模具测试都针对像素中每个覆盖的样本进行。 这有时称为 "超采样"。 相反,在没有采样频率调用(称为多采样)的情况下,无论覆盖多少个样本,像素着色器都会调用一次,而深度/模具测试以采样频率进行。 这两种模式都提供等效的边缘抗锯切。 但是,通过更频繁地调用像素着色器,超采样可提供更好的着色质量。

1. 使用 int/uint 类型时,唯一有效的选项是 **nointerpolation**。

内插修饰符可应用于结构成员或 函数参数,或同时应用于两者。

示例

下面是一些示例结构声明。

struct struct1
{
  int    a;
}

此声明包含一个数组。

struct struct2
{
  int    a;
  float  b;
  int4x4 iMatrix;
}

此声明包括内插修饰符。

struct In
{
  centroid float2 Texcoord;
};

用户定义类型

使用以下语法声明用户定义的类型。

typedef [ 常量 ] 类型名称 [ 索引 ];

参数

项目 说明
[const] 可选。 此关键字将类型显式标记为常量。
类别 标识数据类型;必须是 HLSL 内部数据类型之一。
路径名 唯一标识变量名称的 ASCII 字符串。
编入 可选数组大小。 必须是介于1和4之间的无符号整数。

除了内置的内部数据类型之外,HLSL 还支持用户定义的或自定义的类型,这些类型遵循以下语法:

备注

用户定义的类型不区分大小写。 为方便起见,将在超级全局范围内自动定义以下类型。

typedef vector <bool, #> bool#;
typedef vector <int, #> int#;
typedef vector <uint, #> uint#;
typedef vector <half, #> half#;
typedef vector <float, #> float#;
typedef vector <double, #> double#;

typedef matrix <bool, #, #> bool#x#;
typedef matrix <int, #, #> int#x#;
typedef matrix <uint, #, #> uint#x#;
typedef matrix <half, #, #> half#x#;
typedef matrix <float, #, #> float#x#;
typedef matrix <double, #, #> double#x#;

井号 (#) 表示一个介于1和4之间的整数。

为了与 DirectX 8 效果兼容,以下类型自动在超级全局范围内定义:

typedef int DWORD;
typedef float FLOAT; 
typedef vector <float, 4> VECTOR;
typedef matrix <float, 4, 4> MATRIX;
typedef string STRING;
typedef texture TEXTURE;
typedef pixelshader PIXELSHADER;
typedef vertexshader VERTEXSHADER;

状态对象

使用着色器模型6.3 及更高版本时,应用程序除了可以使用 Direct3D 12 Api 以外,还可以轻松灵活地在 HLSL 着色器代码中直接定义 DXR 状态对象。

在 HLSL 中,状态对象是用以下语法声明的:

syntax复制

Type Name = 
{ 
    Field1,
    Field2,
    ...
};
说明
类别 标识子对象的类型。 必须是受支持的 HLSL 子对象类型之一。
路径名 唯一标识变量名称的 ASCII 字符串。
Field [1,2,...] 子对象的字段。 下面介绍了每种类型的子对象的特定字段。

子对象类型的列表:

StateObjectConfig

StateObjectConfig 子对象类型对应于 D3D12_STATE_OBJECT_CONFIG 结构。

它有一个字段,即一个位标志,该标志是

  • STATE_OBJECT_FLAGS_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITONS
  • STATE_OBJECT_FLAGS_ALLOW_EXTERNAL_DEPENDENCIES_ON_LOCAL_DEFINITIONS

或为零。

示例:

StateObjectConfig MyStateObjectConfig = 
{ 
    STATE_OBJECT_FLAGS_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITONS
};

GlobalRootSignature

GlobalRootSignature 与 D3D12_GLOBAL_ROOT_SIGNATURE 结构相对应。

这些字段包含一些字符串,这些字符串描述了根签名的各个部分。 有关此的参考,请参阅 在 HLSL 中指定根签名

示例:

GlobalRootSignature MyGlobalRootSignature =
{
    "DescriptorTable(UAV(u0)),"                     // Output texture
    "SRV(t0),"                                      // Acceleration structure
    "CBV(b0),"                                      // Scene constants
    "DescriptorTable(SRV(t1, numDescriptors = 2))"  // Static index and vertex buffers.
};

LocalRootSignature

LocalRootSignature 与 D3D12_LOCAL_ROOT_SIGNATURE 结构相对应。

与全局根签名子对象一样,字段包含一些字符串,这些字符串描述了根签名的各个部分。 有关此的参考,请参阅 在 HLSL 中指定根签名

示例:

LocalRootSignature MyLocalRootSignature = 
{
    "RootConstants(num32BitConstants = 4, b1)"  // Cube constants 
};

SubobjectToExportsAssocation

默认情况下,仅在与导出相同的库中声明的子对象可以应用于该导出。 但是,应用程序可以重写该,并获取有关子对象如何与导出有关的信息。 在 HLSL 中,此 "显式关联" 是使用 SubobjectToExportsAssocation 完成的。

SubobjectToExportsAssocation 与 D3D12_DXIL_SUBOBJECT_TO_EXPORTS_ASSOCIATION 结构相对应。

此子对象是用语法声明的

syntax复制

SubobjectToExportsAssocation Name = 
{ 
    SubobjectName,
    Exports
};
说明
路径名 唯一标识变量名称的 ASCII 字符串。
SubobjectName 标识导出的子对象的字符串。
导出 字符串,其中包含以分号分隔的导出列表。

示例:

SubobjectToExportsAssociation MyLocalRootSignatureAssociation =
{
    "MyLocalRootSignature",    // Subobject name
    "MyHitGroup;MyMissShader"  // Exports association 
};

请注意,这两个字段均使用 导出 的名称。 如果应用程序选择执行导出-重命名,则导出的名称可能与 HLSL 中的原始名称不同。

RaytracingShaderConfig

RaytracingShaderConfig 与 D3D12_RAYTRACING_SHADER_CONFIG 结构相对应。

此子对象是用语法声明的

syntax复制

RaytracingShaderConfig Name = 
{ 
    MaxPayloadSize,
    MaxAttributeSize
};
说明
路径名 唯一标识变量名称的 ASCII 字符串。
MaxPayloadSize 每个标量的最大存储 (的数字值在关联 raytracing 着色器的光线负载) 中计为4字节。
MaxAttributeSize 每) 可用于关联 raytracing 着色器的属性的最大 (标量数的数值,最大值为4字节。 值不能超过 D3D12_RAYTRACING_MAX_ATTRIBUTE_SIZE_IN_BYTES

示例:

RaytracingShaderConfig MyShaderConfig =
{
    16,  // Max payload size
    8    // Max attribute size
};

RaytracingPipelineConfig

RaytracingPipelineConfig 与 D3D12_RAYTRACING_PIPELINE_CONFIG 结构相对应。

此子对象是用语法声明的

syntax复制

RaytracingPipelineConfig Name = 
{ 
    MaxTraceRecursionDepth
};
说明
路径名 唯一标识变量名称的 ASCII 字符串。
MaxTraceRecursionDepth 用于 raytracing 管道中的 ray 递归的数值限制。 它是0到31之间的数字,含0和31。

示例:

RaytracingPipelineConfig MyPipelineConfig =
{
    1  // Max trace recursion depth
};

由于 raytracing 递归会带来性能开销,因此应用程序应使用所需结果所需的最低递归深度。

如果着色器调用尚未达到最大递归深度,则可以多次调用 TraceRay 。 但如果它们达到或超出最大递归深度,则调用 TraceRay 会将设备置于已删除状态。 因此,如果 raytracing 着色器已经满足或超出最大递归深度,则应该小心停止调用 TraceRay。

TriangleHitGroup

TriangleHitGroup 对应于其 Type 字段设置为D3D12_HIT_GROUP_TYPE_TRIANGLESD3D12_HIT_GROUP_DESC结构。

此子对象是用语法声明的

syntax复制

TriangleHitGroup Name = 
{ 
    AnyHitShader,
    ClosestHitShader
};
说明
路径名 唯一标识变量名称的 ASCII 字符串。
AnyHitShader 用于命中组的 anyhit 着色器的字符串名称,或者为空字符串。
ClosestHitShader 命中组的最接近的命中着色器的字符串名称,或者为空字符串。

示例:

TriangleHitGroup MyHitGroup =
{
    "",                    // AnyHit
    "MyClosestHitShader",  // ClosestHit
};

请注意,这两个字段均使用 导出 的名称。 如果应用程序选择执行导出-重命名,则导出的名称可能与 HLSL 中的原始名称不同。

过程PrimitiveHitGroup

过程PrimitiveHitGroup 对应于一个D3D12_HIT_GROUP_DESC,其Type 字段设置为D3D12_HIT_GROUP_TYPE_PROCEDURAL_PRIMITIVE。

此子对象是使用 语法声明的

syntax复制

ProceduralPrimitiveHitGroup Name = 
{ 
    AnyHitShader,
    ClosestHitShader,
    IntersectionShader
};
说明
名字 唯一标识变量名称的 ASCII 字符串。
AnyHitShader 命中组的 anyhit 着色器字符串名称,或空字符串。
ClosestHitShader 命中组最接近的命中着色器或空字符串的字符串名称。
IntersectionShader 命中组的交集着色器字符串名称,或空字符串。

示例:

ProceduralPrimitiveHitGroup MyProceduralHitGroup
{
    "MyAnyHit",       // AnyHit
    "MyClosestHit",   // ClosestHit
    "MyIntersection"  // Intersection
};

请注意,这三个字段 使用导出的名称 。 如果应用程序选择执行导出重命名,则导出的名称可能不同于 HLSL 中的原始名称。

备注

子对象具有"关联"或"哪个子对象与哪个导出一起"的概念。

通过着色器代码指定子对象时,选择"哪个子对象与哪个导出一起"遵循 DXR规范 中概述的规则。 具体而言,假设应用程序具有一些导出。 如果应用程序通过着色器代码和根签名 B 通过应用程序代码将导出与根签名 A 关联,则使用 B。 "使用 B"而不是"生成错误"的设计使应用程序能够方便地使用应用程序代码重写 DXIL 关联,而不是强制重新编译着色器以解决不匹配的问题。

函数声明语法

HLSL 函数是使用以下语法声明的。

[StorageClass ][剪贴板 () ] [precise ] Return Value Name _ ( [ ArgumentList ] ) : [ Semantic ] { [ StatementBlock ] };

参数

StorageClass

重新定义函数声明的修饰符。 inline 当前是唯一的修饰符值。 修饰符值必须是 内联 的,因为它也是默认值。 因此,无论是否指定内联 ,函数都是内联的,并且 HLSL 中所有函数都是内联的。 内联函数在每个函数调用的编译 (生成) 主体副本。 这样做是为了降低调用函数的开销。

剪贴板

剪辑平面的可选列表,最多 6 个用户指定的剪辑平面。 这是适用于 SV _ ClipDistance 的备用机制, 适用于功能级别 9 _ x 及更高版本。

名字

唯一标识着色器函数名称的 ASCII 字符串。

ArgumentList

可选参数列表,它是传入函数的参数  逗号分隔列表。

语义

用于标识返回数据预期用法的可选字符串 (请参阅 DirectX HLSL (语义) ) 。

StatementBlock

可选语句,这些语句是函数的主体。 没有主体定义的函数称为函数原型;必须先在其他地方定义原型函数的主体,然后才能调用该函数。

返回值

返回类型可以是这些 HLSL 类型中的任意一种

备注

此页上的语法几乎描述了每种类型的 HLSL 函数,其中包括顶点着色器、像素着色器以及帮助程序函数。 虽然几何着色器也是使用函数实现的,但语法稍微复杂一些,因此有一个单独的页面定义几何着色器函数声明 (请参阅 Geometry-Shader Object (DirectX HLSL ) ) 。

只要为函数提供参数类型和/或参数顺序的唯一组合,就可以重载函数。 HLSL 还实现许多内置函数或 内部函数

可以使用 clipplanes 属性指定用户 特定的剪贴 平面。 Windows这些剪裁平面应用于绘制的所有基元。 剪 贴板属性 的工作方式与 SV _ ClipDistance 类似,但适用于所有硬件功能级别 9 _ x 及更高版本。 有关详细信息,请参阅功能 级别 9 硬件 上的用户剪辑平面

示例

此示例来自 BasicHLSL10 示例 中的BasicHLSL10.fx。

hlsl

struct VS_OUTPUT
{
    float4 Position   : SV_POSITION; 
    float4 Diffuse    : COLOR0;
    float2 TextureUV  : TEXCOORD0;
};

VS_OUTPUT RenderSceneVS( float4 vPos : POSITION,
                         float3 vNormal : NORMAL,
                         float2 vTexCoord0 : TEXCOORD,
                         uniform int nNumLights,
                         uniform bool bTexture,
                         uniform bool bAnimate )
{
    VS_OUTPUT Output;
    ...
    return Output;    
}

AdvancedParticles 示例中 AdvancedParticles.fx的此示例演示了对返回类型使用语义。

hlsl

//
// PS for particles
//
float4 PSPointSprite(PSSceneIn input) : SV_Target
{   
    return g_txDiffuse.Sample( g_samLinear, input.tex ) * input.color;
}

Common-Shader Core - Win32 apps | Microsoft Docs

Variable Syntax - Win32 apps | Microsoft Docs

RWBuffer - Win32 apps | Microsoft Docs

undef 指令 - Win32 apps | Microsoft Docs

RWStructuredBuffer - Win32 apps | Microsoft Docs

numthreads - Win32 apps | Microsoft Docs

///

///

/

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Game_jqd/article/details/124185088

智能推荐

Linux笔记——/etc/shadow文件-程序员宅基地

文章浏览阅读7.5k次。Linux笔记——/etc/shadow文件_/etc/shadow

java把秒时长转换为分钟_java - 将秒值转换为小时分钟秒?-程序员宅基地

文章浏览阅读4.9k次。java - 将秒值转换为小时分钟秒?我一直在尝试将秒值(在BigDecimal变量中)转换为editText中的字符串,如“1小时22分33秒”或类似的东西。我试过这个:String sequenceCaptureTime = "";BigDecimal roundThreeCalc = new BigDecimal("0");BigDecimal hours = new BigDecimal..._java hh:mm:ss转分钟

Sentinel详解_sentinel文档-程序员宅基地

文章浏览阅读966次。Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。中文官网地址:https://sentinelguard.io/zh-cn/docs/introduction.html当调用链路中某个资源出现不稳定,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源。sentinel处理这个问题采取了两中方式:2、下载Sentinelhttps://github.com/alibaba/Sentinel/releases下载完成后找到下载的目录_sentinel文档

360 支持linux版本下载地址,360安全浏览器国产稳定版本发布,提供deb软件包下载,附介绍...-程序员宅基地

文章浏览阅读2.2k次。360安全浏览器已经正式上线国产版,提供有deb软件包下载,为稳定版本(browser360-cn-stable_10.0.2001.0-1_amd64.deb),当前版本号为10.0.2001.0,内核是Chromium 63。有用户反馈,使用-2的有依赖问题,-1没有依赖问题,能正常使用,在下载链接中提供该deb包下载,可参考安装360浏览器稳定版依赖关系不满足的解决思路一文。360安全浏览器..._360deb

cobbler源码安装-程序员宅基地

文章浏览阅读608次。cobbler源码安装1. cobbler简介Cobbler是一个Linux服务器安装的服务,可以通过网络启动(PXE)的方式来快速安装、重装物理服务器和虚拟机,同时还可以管理DHCP,DNS等。Cobbler可以使用命令行方式管理,也提供了基于Web的界面管理工具(cobbler-web),还提供了API接口,可以方便二次开发使用。Cobbler是较早前的kickstart的升级版,优点是比较容易配置,还自带web界面比较易于管理。Cobbler内置了一个轻量级配置管理系统,但它也支持和其它配置_cobbler源码安装

踩雷:Win10安装anaconda3-4.4.0+tensorflow-gpu1.12.0+keras2.2.4_anaconda3 4.4.0-程序员宅基地

文章浏览阅读477次。**Win10安装anaconda3-4.4.0+tensorflow-gpu1.12.0+keras2.2.4**本人的电脑配置:NVIDIA GTX1050ti这次安装也是破费周转,特此做下记录。不会再详细地写出具体的操作,大多数都用链接代替了。1.安装anacondaWindows安装anaconda2.安装cuda下载cudnntensorflow各个版本的CUDA以及Cudnn版本对应关系首先要清楚自己需要装什么版本的tensorflow。根据自己项目的实际需求确定tensorf_anaconda3 4.4.0

随便推点

Unknown URL-程序员宅基地

文章浏览阅读1.8k次。菜鸟错误大全(六)我们都是从新手一步一个坑踩过来的,下面我们来讲讲会遇到的常见错误和解决办法: Unknown URL content://com.exaple.databasetest.provider/book:这是写错包名了,应该为“content://com.example.databasetest.provider/book”_unknown url

【微信小程序】支付及退款流程详解_微信小程序退款前端开发-程序员宅基地

文章浏览阅读2.5k次,点赞2次,收藏15次。一. 支付支付主要分为几个步骤:前端携带支付需要的数据(商品id,购买数量等)发起支付请求后端在接收到支付请求后,处理支付数据,然后携带处理后的数据请求 微信服务器 的 支付统一下单接口后端接收到上一步请求微信服务器的返回数据,再次处理,然后返回前端让前端可以开始支付。前端进行支付动作前端支付完成后,微信服务器会向后端发送支付通知(也就是微信要告诉你客户已经付过钱了),后端根据这个通..._微信小程序退款前端开发

Sublime Text 3正式版发布_sublime3 toolchain-程序员宅基地

文章浏览阅读2.2w次。Sublime Text 3正式版发布作者:chszs,转载需注明。博客主页:http://blog.csdn.net/chszs一、下载地址:1. Windows 32位版http://c758482.r82.cf2.rackcdn.com/Sublime%20Text%20Build%203010%20Setup.exe2. Windows 64位版http://c758482.r82.cf2_sublime3 toolchain

flutter 参数函数_Flutter完整开发实战详解(一、基础)-程序员宅基地

文章浏览阅读776次。前言在如今的 Flutter 大潮下,本系列是让你看完会安心的文章。本系列将完整讲述:如何入门 Flutter 开发,如何快速从 0 开发一个完整的 Flutter APP,配套高完成度 Flutter 开源项目 GSYGithubAppFlutter,提供 Flutter 的开发技巧和问题处理,之后深入源码和实战为你全面解析 Flutter。 笔者相继开发过 Flutter、React Nat..._flutter 函数详解

Java实现第八届蓝桥杯杨辉三角-程序员宅基地

文章浏览阅读3.5k次。杨辉三角杨辉三角也叫帕斯卡三角,在很多数量关系中可以看到,十分重要。第0行: 1第1行: ..._杨辉三角java第八届蓝桥杯

硕士阶段人工智能有哪些比较好的发论文的方向?_硕士强化学习做什么方向好毕业-程序员宅基地

文章浏览阅读3.7k次。人们对于一些新时代诞生得词语总是会提出疑问,比如说什么是人工智能?在帮助盟军通过破解纳粹加密机Enigma赢得第二次世界大战后不到十年,数学家艾伦·图灵(Alan Turing)第二次改变了历史,提出了一个简单的问题:“机器能思考吗?”图灵1950年的论文“计算机与智能”及其随后的图灵测试确立了人工智能的基本目标和愿景。从本质上讲,人工智能是计算机科学的一个分支,旨在肯定地回答图灵的问题。它是在机器中复制或模拟人类智能的努力。人工智能的广泛目标引发了许多问题和辩论如此之多,以至于没有一个单一的领域定义被_硕士强化学习做什么方向好毕业

推荐文章

热门文章

相关标签