Programming guide for HLSL (二)

在 Direct3D 10 中使用着色器

管道有三个着色器阶段,每个阶段都使用 HLSL 着色器进行编程。 所有 Direct3D 10 着色器均以 HLSL 编写,面向着色器模型 4。

Direct3D 9 和 Direct3D 10 之间的差异:

  • 与使用中间汇编语言创作的 Direct3D 9 着色器模型不同,着色器模型 4.0 着色器仅在 HLSL 中创作。 仍支持将着色器脱机编译为设备可使用的字节码,建议在大多数情况下使用。

此示例仅使用顶点着色器。 由于所有着色器都是从通用着色器核心构建的,因此了解如何使用顶点着色器与使用几何图形或像素着色器非常相似。

创建 HLSL 着色器 (此示例使用顶点着色器 HLSLWithoutFX.vsh) 后,需要为使用它的特定管道阶段做好准备。 为此,需要:

需要为管道中的每个着色器重复这些步骤。

编译着色器

第一步是编译着色器,检查是否正确编码了 HLSL 语句。 为此,可以调用 D3D10CompileShader,并按如下所示提供多个参数:

IPD3D10Blob * pBlob;
    
        
    // Compile the vertex shader from the file
    D3D10CompileShader( strPath, strlen( strPath ), "HLSLWithoutFX.vsh", 
        NULL, NULL, "Ripple", "vs_4_0", dwShaderFlags, &pBlob, NULL );

此函数采用以下参数:

  • 文件名名称 (名称字符串的长度(以字节) 着色器)。 此示例仅在文件 HLSLWithoutFX.vsh 文件中使用 (着色器,其中文件扩展名 .vsh 是顶点着色器名称的缩写) 。

  • 着色器函数名称。 此示例从使用单个输入的处理函数编译顶点着色器,该函数返回输出结构 (该函数来自 HLSLWithoutFX 示例) :

VS_OUTPUT Ripple( in float2 vPosition : POSITION )

  • 指向着色器使用的所有宏的指针。 使用 D3D10 SHADER 宏来帮助定义宏;只需创建一个名称字符串,其中包含所有宏名称 (,每个名称由空格) 分隔,定义字符串 (每个宏主体由空格 _ _) 分隔。 这两个字符串都需要以 NULL 终止。

  • 指向需要包含的其他任何文件的指针,使着色器能够编译。 这会使用 ID3D10Include 接口,该接口具有两个用户实现的方法:Open 和 Close。 若要使此操作正常工作,需要实现 Open 和 Close 方法的正文;在 Open 方法中添加用于打开所需的任何包含文件的代码,在 Close 函数中添加代码,以在完成后关闭文件。

  • 要编译的着色器函数的名称。 此着色器编译"波纹"函数。

  • 编译时要作为目标的着色器配置文件。 由于可以将函数编译为顶点、几何图形或像素着色器,因此配置文件会告知编译器着色器的类型以及要比较代码的着色器模型。

  • 着色器编译器标志。 这些标志告知编译器要放入已编译输出的信息,以及希望输出代码如何优化:用于速度、调试等。有关 可用标志 (,请参阅 Direct3D 10 ) 效果常量。 该示例包含一些可用于为项目设置编译器标志值的代码 - 这主要涉及是否要生成调试信息的问题。

  • 指向包含已编译着色器代码的缓冲区的指针。 缓冲区还包含编译器标志请求的任何嵌入式调试和符号表信息。

  • 指向缓冲区的指针,该缓冲区包含编译过程中遇到的错误和警告列表,这些错误和警告与在编译着色器时运行调试器时在调试输出中看到的消息相同。 如果 不希望错误返回到缓冲区,则 NULL 是可接受的值。

如果着色器编译成功,则指向着色器代码的指针作为 ID3D10Blob 接口返回。 它被称为 Blob 接口,因为指针指向内存中由 DWORD 数组所包含的位置。 提供了 接口,以便你可以获取指向下一步中将需要的已编译着色器的指针。

从 2006 年 12 月 SDK 开始,DirectX 10 HLSL 编译器现在是 DirectX 9 和 DirectX 10 中的默认编译器。 有关详细信息 ,请参阅效果编译器 工具。

获取指向已编译着色器指针

多个 API 方法需要指向已编译着色器的指针。 此参数通常称为 pShaderBytecode, 因为它指向表示为字节代码序列的已编译着色器。 若要获取指向已编译着色器的指针,请首先通过调用 D3D10CompileShader 或类似函数来编译着色器。 如果编译成功,则编译的着色器将在 ID3D10Blob 接口中 返回。 最后,使用 GetBufferPointer 方法返回指针。

创建着色器对象

编译着色器后,调用 CreateVertexShader 创建着色器对象:

ID3D10VertexShader ** ppVertexShader
    ID3D10Blob pBlob;


    // Create the vertex shader
    hr = pd3dDevice->CreateVertexShader( (DWORD*)pBlob->GetBufferPointer(),
        pBlob->GetBufferSize(), &ppVertexShader );

    // Release the pointer to the compiled shader once you are done with it
    pBlob->Release();

若要创建着色器对象,将指向已编译着色器的指针传递到 CreateVertexShader。 由于你首先必须成功编译着色器,因此此调用几乎一定会通过,除非你计算机上存在内存问题。

可创建任何喜欢的着色器对象,并仅保留指向这些对象的指针。 此机制适用于几何图形和像素着色器,前提是在调用编译方法 (时,将着色器配置文件) 与接口名称匹配 (调用 create 方法) 。

设置着色器对象

最后一步是将着色器设置为管道阶段。 由于管道中有三个着色器阶段,因此需要执行三个 API 调用,每个阶段一个。

// Set a vertex shader
    pd3dDevice->VSSetShader( g_pVS10 );

对 VSSetShader 的调用采用指向在步骤 1 中创建的顶点着色器的指针。 这会在设备中设置着色器。 顶点着色器阶段现在使用其顶点着色器代码进行初始化,所有保留的都是初始化任何着色器变量。

针对所有 3 个着色器阶段重复上述步骤

重复这一组相同的步骤,以生成输出到像素着色器的任何顶点或像素着色器,甚至是几何着色器。

优化 HLSL 着色器

本部分介绍可用于优化着色器常规用途策略。 可以将这些策略应用于在任何平台上以任何语言编写的着色器。

了解在何处执行着色器计算

顶点着色器执行的操作包括提取顶点和执行顶点数据的矩阵转换。 通常,顶点着色器按每个顶点执行一次。

像素着色器执行的操作包括提取纹理数据和执行照明计算。 通常,对于给定的几何图形块,像素着色器每像素执行一次。

通常,场景中的像素数超过顶点数,因此像素着色器的执行频率高于顶点着色器。

设计着色器算法时,请记住以下事项:

  • 如果可能,请对顶点着色器执行计算。 对像素着色器执行的计算比在顶点着色器上执行的计算要昂贵得多。
  • 请考虑使用每顶点计算来提高密集网格等情况下的性能。 对于密集网格,每个顶点的计算可能会生成与使用每像素计算生成的结果在视觉上不一致的结果。

跳过不必要的指令

在 HLSL 中,动态分支提供限制执行指令数的能力。 因此,动态分支有助于加快着色器执行时间。 如果未显示几何图形或像素,请使用动态分支退出着色器或限制指令。 例如,如果像素未亮起,则执行照明算法没有意义。

下表列出了一些可以在着色器中测试条件并使用动态分支跳过不必要的指令的情况。 该表并不全面。 相反,它旨在提供优化代码的思路。

要检查的条件着色器中的响应
Alpha 检查确定不会看到像素。跳过着色器的其余部分。
像素或几何图形是完全伪造的。跳过着色器的其余部分。
外观权重为零。跳过跳过。
光衰减为零。跳过照明。
非正 Lambertian 术语。跳过照明。

Pack 变量和内插

请注意着色器数据所需的空间。 将尽可能多的信息打包到变量或内插中。 有时,两个变量的信息可以打包到单个变量的内存空间中。

降低着色器复杂性

使着色器保持小而简单。 通常,与具有更多指令的着色器相比,具有较少指令的着色器的执行速度更快。 此外,调试和优化较小、不太复杂的着色器也更容易。

//

在 Visual Studio 中调试着色器

调试着色器的最新工具现在作为 Microsoft Visual Studio 中的一项功能提供,Visual Studio图形调试器。 此新工具替代了适用于 Windows 工具的PIX。 Visual Studio图形调试器极大地提高了可用性、对 Windows 8 和 Direct3D 11.1 的支持,以及与传统 Visual Studio 功能(如调用堆栈和HLSL调试的调试窗口)的集成。 有关此新功能的信息,请参阅 调试 DirectX 图形

///

编译着色器

Microsoft Visual Studio 2012 现在可以从包括在 C++ 项目中的 * .hlsl 文件中编译着色器代码。

在生成过程中,Visual Studio 2012 使用fxc.exe HLSL 代码编译器将 .hlsl 文件编译为二进制着色器对象文件或头文件中定义的字节数组。 HLSL 代码编译器编译项目中每个 .hlsl 文件的方式取决于你为该文件指定 Ouput Files 属性的方式。 有关 HLSL 属性页的信息,请参阅 HLSL 属性页

使用的编译方法通常取决于 * .hlsl 文件的大小。 如果在标头中包括大量字节代码,则增加应用的大小和初始加载时间。 还可以强制所有字节代码驻留在内存中,即使在创建着色器后,也会浪费资源。 但是,在标头中包括字节代码时,可以降低代码复杂性并简化着色器创建。

现在,让我们看看为着色器代码编译着色器代码和文件扩展名约定的各种方法。

使用着色器代码文件扩展名

若要符合 Microsoft 约定,请对着色器代码使用以下文件扩展名:

  • 扩展名为 .hlsl 的文件包含高级着色语言 (HLSL) 源代码。
  • 扩展名为 .cso 的文件保留经过编译的着色器对象。
  • 扩展名为 .h 的文件是头文件,但在着色器代码上下文中,此头文件定义保留着色器数据的字节数组。

在生成时编译对象文件

如果将 .hlsl 文件编译为二进制着色器对象文件,则应用需要从这些对象文件读取数据 (.cso 是这些对象文件) 的默认扩展名,将数据分配给字节数组,并基于这些字节数组创建着色器对象。 例如,若要创建顶点着色器 (ID3D11VertexShader * *) ,请 调用 ID3D11Device::CreateVertexShader方法,该方法具有包含已编译顶点着色器字节代码的字节数组。 Direct3D 教程示例演示如何从从 .cso 二进制着色器对象文件获取的字节数组创建着色器对象。 在 Direct3D教程示例 的此示例代码中,SimpleVertexShader.hlsl 文件的 Ouput Files 属性指定编译为 SimpleVertexShader.cso 对象文件。

auto vertexShaderBytecode = reader->ReadData("SimpleVertexShader.cso");
        ComPtr<ID3D11VertexShader> vertexShader;
        DX::ThrowIfFailed(
            m_d3dDevice->CreateVertexShader(
                vertexShaderBytecode->Data,
                vertexShaderBytecode->Length,
                nullptr,
                &vertexShader
                )

在生成时编译到头文件

如果将 .hlsl 文件编译为头文件中定义的字节数组,则需要在代码中包含这些头文件。 媒体 扩展示例 演示如何从头文件中定义的字节数组创建着色器对象,这些字节数组在编译时包括在项目中。 在媒体扩展示例的此示例 代码中,PixelShader.hlsl 文件的 Ouput Files 属性指定编译为 PixelShader.h 头文件中定义的 g _ psshader 字节数组。

#       include "PixelShader.h"
        ComPtr<ID3D11PixelShader> m_pPixelShader;
        hr = pDevice->CreatePixelShader(g_psshader, sizeof(g_psshader), nullptr, &m_pPixelShader);

使用 D3DCompileFromFile 进行编译

还可以运行时使用 D3DCompileFromFile 函数编译着色器代码。 若要详细了解如何这样做,请参阅 如何:编译着色器

 备注

Windows应用商店应用支持使用 D3DCompileFromFile进行开发,但不支持部署。

///

解压缩和打包 DXGI _ FORMAT In-Place图像编辑

D3DX DXGIFormatConvert.inl 文件包含可在 Direct3D 11 硬件上的计算着色器或像素着色器中使用的内联格式 _ 转换函数。 可以在应用程序中使用这些函数同时从纹理读取和写入纹理。 也就是说,可以执行就地图像编辑。 若要使用这些内联格式转换函数,请在你的应用程序中包括 D3DX _ DXGIFormatConvert.inl 文件。

D3DX _ DXGIFormatConvert.inl 标头在旧版 DirectX SDK 中提供。 它还包含在Microsoft.DXSDK.D3DX NuGet包中。

Direct3D 11 的 Texture1D、Texture2D 或 Texture3D 资源的无序访问视图 (UAV) 支持从计算着色器或像素着色器对内存进行随机访问读取和写入。 但是,Direct3D 11 支持同时读取和写入 DXGI FORMAT _ _ R32 _ UINT 纹理格式。 例如,Direct3D 11 不支持同时读取和写入其他更有用的格式,例如 DXGI _ FORMAT _ R8G8B8A8 _ UNORM。 只能使用 UAV 随机访问写入此类其他格式,或者只能使用着色器 资源视图 (SRV) 从此类其他格式读取的随机访问。 格式转换硬件不能同时读取和写入此类其他格式。

但是,创建 UAV 时,仍可通过将纹理强制转换到 DXGI FORMAT R32 UINT 纹理格式,同时读取和写入此类其他格式,只要资源的原始格式支持强制转换到 _ _ _ DXGI FORMAT _ _ R32 _ UINT。 每个元素格式最多 32 位支持强制转换到 DXGI _ FORMAT _ R32 _ UINT。 通过创建 UAV 时将纹理强制转换到 DXGI _ FORMAT _ R32 UINT 纹理格式,只要着色器在读取和打包写入时执行手动格式解包,就可以同时对纹理执行读取和 _ 写入操作。

将纹理强制转换到 DXGI FORMAT R32 UINT 纹理格式的好处是,稍后可以使用适当的格式 (例如 _ _ _ ,DXGI FORMAT _ _ R16G16 _ FLOAT) 与相同纹理上的其他视图(如呈现目标视图 (RTV) 或 SRP)一起使用。 因此,硬件可以执行典型的自动格式解压缩和打包,可以执行纹理筛选,等等,没有任何硬件限制。

以下方案要求应用程序执行以下一系列操作来执行就地图像编辑。

假设你想要创建一个纹理,可以在该纹理上使用像素着色器或计算着色器执行就地编辑,并且希望纹理数据以以下 TYPELESS 格式之一的后代格式存储:

  • DXGI _ FORMAT _ R10G10B10A2 _ 无类型
  • DXGI _ FORMAT _ R8G8B8A8 _ 无类型
  • DXGI _ FORMAT _ B8G8R8A8 _ 无类型
  • DXGI _ FORMAT _ B8G8R8X8 _ 无类型
  • DXGI _ FORMAT _ R16G16 _ 无类型

例如,DXGI _ FORMAT _ R10G10B10A2 _ UNORM 格式是 DXGI _ FORMAT _ R10G10B10A2 _ TYPELESS 格式的后代。 因此,DXGI _ FORMAT _ R10G10B10A2 UNORM 支持如下序列中所述 _ 的使用模式。 从 DXGI FORMAT R32 TYPELESS 降序的格式(如 _ _ _ DXGI _ FORMAT _ R32 _ FLOAT)通常受支持,无需以下序列中所述的任何格式转换帮助。

执行就地图像编辑

  1. 使用上一方案中指定的相应 TYPELESS 相关格式以及所需的绑定标志(如 D3D11 _ BIND _ UNORDERED _ ACCESS | D3D11 _ BIND _ SHADER _ 资源)创建纹理。

  2. 对于就地图像编辑,请创建采用 DXGI _ FORMAT _ R32 _ UINT 格式的 UAV。 Direct3D 11 API 通常不允许在不同格式"系列"之间转换。 但是,Direct3D 11 API 使用 DXGI _ FORMAT _ R32 UINT 格式引发 _ 异常。

  3. 在计算着色器或像素着色器中,使用 D3DX DXGIFormatConvert.inl 文件中提供的适当内联格式包和解压缩 _ 函数。 例如,假设纹理的 DXGI _ FORMAT _ R32 _ UINT UAV 确实保存 DXGI _ FORMAT _ R10G10B10A2 _ UNORM 格式的数据。 应用程序将 UAV 中的 uint 读入着色器后,必须调用以下函数来解压缩纹理格式:

XMFLOAT4 D3DX_R10G10B10A2_UNORM_to_FLOAT4(UINT packedInput)

然后,若要在同一着色器中写入 UAV,应用程序将调用以下函数,将着色器数据打包到应用程序可写入 UAV 的 uint 中:

UINT D3DX_FLOAT4_to_R10G10B10A2_UNORM(hlsl_precise XMFLOAT4 unpackedInput)

  1. 然后,应用程序可以使用所需的格式创建其他视图,例如 SRV。 例如,如果资源创建为 _ _ _ DXGI _ FORMAT _ R10G10B10A2 TYPELESS,则应用程序可以创建采用 DXGI FORMAT R10G10B10A2 _ UNORM 格式的 SRV。 当着色器访问该 SRV 时,硬件可以照常执行自动类型转换。

 备注

如果着色器只能写入 UAV 或读取为 SRV,则不需要此转换工作,因为可以使用完全类型 UAV 或 SRV。 只有在想要同时读取和写入纹理的 UAV 时,D3DX _ DXGIFormatConvert.inl 中提供的格式转换函数才可能有用。

下面是 D3DX _ DXGIFormatConvert.inl 文件中包含的格式转换函数的列表。 这些函数按它们解压缩和打包的 DXGI _ 格式进行分类。 每个支持的格式都来自上述方案中列出的 TYPELESS 格式之一,并支持将强制转换到 DXGI FORMAT _ _ R32 _ UINT 作为 UAV。

DXGI _ FORMAT _ R10G10B10A2 _ UNORM

XMFLOAT4 D3DX_R10G10B10A2_UNORM_to_FLOAT4(UINT packedInput)
UINT     D3DX_FLOAT4_to_R10G10B10A2_UNORM(hlsl_precise XMFLOAT4 unpackedInput)

DXGI _ FORMAT _ R10G10B10A2 _ UINT

XMUINT4 D3DX_R10G10B10A2_UINT_to_UINT4(UINT packedInput)
UINT    D3DX_UINT4_to_R10G10B10A2_UINT(XMUINT4 unpackedInput)

DXGI _ FORMAT _ R8G8B8A8 _ UNORM

XMFLOAT4 D3DX_R8G8B8A8_UNORM_to_FLOAT4(UINT packedInput)
UINT     D3DX_FLOAT4_to_R8G8B8A8_UNORM(hlsl_precise XMFLOAT4 unpackedInput)

DXGI _ FORMAT _ R8G8B8A8 _ UNORM _ SRGB

XMFLOAT4 D3DX_R8G8B8A8_UNORM_SRGB_to_FLOAT4_inexact(UINT packedInput) *
XMFLOAT4 D3DX_R8G8B8A8_UNORM_SRGB_to_FLOAT4(UINT packedInput)
UINT     D3DX_FLOAT4_to_R8G8B8A8_UNORM_SRGB(hlsl_precise XMFLOAT4 unpackedInput)

备注

_inexact-type 函数使用精度不够高的着色器指令来给出确切的答案。 替代函数使用着色器中存储的查找表提供确切的 SRGB->浮点转换。

DXGI _ FORMAT _ R8G8B8A8 _ UINT

XMUINT4 D3DX_R8G8B8A8_UINT_to_UINT4(UINT packedInput)
XMUINT  D3DX_UINT4_to_R8G8B8A8_UINT(XMUINT4 unpackedInput)

DXGI _ FORMAT _ R8G8B8A8 _ SNORM

XMFLOAT4 D3DX_R8G8B8A8_SNORM_to_FLOAT4(UINT packedInput)
UINT     D3DX_FLOAT4_to_R8G8B8A8_SNORM(hlsl_precise XMFLOAT4 unpackedInput)

DXGI _ FORMAT _ R8G8B8A8 _ SINT

XMINT4 D3DX_R8G8B8A8_SINT_to_INT4(UINT packedInput)
UINT   D3DX_INT4_to_R8G8B8A8_SINT(XMINT4 unpackedInput)

DXGI _ 格式 _ B8G8R8A8 _ UNORM

XMFLOAT4 D3DX_B8G8R8A8_UNORM_to_FLOAT4(UINT packedInput)
UINT     D3DX_FLOAT4_to_B8G8R8A8_UNORM(hlsl_precise XMFLOAT4 unpackedInput)

DXGI _ 格式 _ B8G8R8A8 _ UNORM _ SRGB

XMFLOAT4 D3DX_B8G8R8A8_UNORM_SRGB_to_FLOAT4_inexact(UINT packedInput) *
XMFLOAT4 D3DX_B8G8R8A8_UNORM_SRGB_to_FLOAT4(UINT packedInput)
UINT     D3DX_FLOAT4_to_R8G8B8A8_UNORM_SRGB(hlsl_precise XMFLOAT4 unpackedInput)

备注

_inexact-type 函数使用精度不够高的着色器指令来给出确切的答案。 替代函数使用着色器中存储的查找表提供确切的 SRGB->浮点转换。

DXGI _ 格式 _ B8G8R8X8 _ UNORM

XMFLOAT3 D3DX_B8G8R8X8_UNORM_to_FLOAT3(UINT packedInput)
UINT     D3DX_FLOAT3_to_B8G8R8X8_UNORM(hlsl_precise XMFLOAT3 unpackedInput)

DXGI _ 格式 _ B8G8R8X8 _ UNORM _ SRGB

XMFLOAT3 D3DX_B8G8R8X8_UNORM_SRGB_to_FLOAT3_inexact(UINT packedInput) *
XMFLOAT3 D3DX_B8G8R8X8_UNORM_SRGB_to_FLOAT3(UINT packedInput)
UINT     D3DX_FLOAT3_to_B8G8R8X8_UNORM_SRGB(hlsl_precise XMFLOAT3 unpackedInput)

备注

_inexact-type 函数使用精度不够高的着色器指令来给出确切的答案。 替代函数使用着色器中存储的查找表提供确切的 SRGB->浮点转换。

DXGI _ FORMAT _ R16G16 _ FLOAT

XMFLOAT2 D3DX_R16G16_FLOAT_to_FLOAT2(UINT packedInput)
UINT     D3DX_FLOAT2_to_R16G16_FLOAT(hlsl_precise XMFLOAT2 unpackedInput)

DXGI _ FORMAT _ R16G16 _ UNORM

XMFLOAT2 D3DX_R16G16_UNORM_to_FLOAT2(UINT packedInput)
UINT     D3DX_FLOAT2_to_R16G16_UNORM(hlsl_precise FLOAT2 unpackedInput)

DXGI _ FORMAT _ R16G16 _ UINT

XMUINT2 D3DX_R16G16_UINT_to_UINT2(UINT packedInput)
UINT    D3DX_UINT2_to_R16G16_UINT(XMUINT2 unpackedInput)

DXGI _ FORMAT _ R16G16 _ SNORM

XMFLOAT2 D3DX_R16G16_SNORM_to_FLOAT2(UINT packedInput)
UINT     D3DX_FLOAT2_to_R16G16_SNORM(hlsl_precise XMFLOAT2 unpackedInput)

DXGI _ FORMAT _ R16G16 _ SINT

XMINT2 D3DX_R16G16_SINT_to_INT2(UINT packedInput)
UINT   D3DX_INT2_to_R16G16_SINT(XMINT2 unpackedInput)

///

使用 HLSL 最小精度

从 Windows 8开始,图形驱动程序可以使用大于或等于其指定位精度的任何精度来实现最小精度HLSL标量数据类型。 当 HLSL 最小精度着色器代码用于实现 HLSL 最小精度的硬件上时,占用的内存带宽更少,因此也使用较少的系统电源。

可以通过使用 D3D11 FEATURE _ _ SHADER _ MIN PRECISION _ _ SUPPORT值调用 ID3D11Device::CheckFeatureSupport来查询图形驱动程序提供的最小精度支持。 有关详细信息,请参阅 HLSL 最小精度支持

声明具有最小精度数据类型的变量

若要在 HLSL 着色器代码中使用最小精度,请为矢量) 、min16int、min10float 等声明类型为 min16float (min16float4 的单个变量。 使用这些变量,着色器代码指示它不需要比变量指示的精度更高。 但硬件可以忽略最小精度指示器,以完全 32 位精度运行。 在利用最小精度的硬件上使用着色器代码时,使用的内存带宽较少,因此,只要着色器代码预期比它指定的精度更高,系统电源也更少。

无需创作多个着色器,这些着色器无需使用最小精度。 相反,创建具有最小精度的着色器,如果图形驱动程序报告它不支持任何最小精度,则最小精度变量的行为完全为 32 位精度。 HLSL 最小精度着色器在低于 Windows 8 的操作系统上不起作用,因此,如果计划以早期操作系统为目标,则需要创作多个着色器,有些着色器会使用,而其他着色器不使用最小精度。

 备注

请勿在着色器内的不同精度级别之间进行数据切换,因为这些类型的转换是浪费的,会降低性能。 例外情况是着色器常量仍始终为 32 位,但供应商可以设计图形硬件,这些硬件可自由向下转换为 HLSL 指令读取可能使用的任何较低精度。

通过使用最小精度,可以在着色器代码的各个部分控制计算的精度。

HLSL 最小精度规则类似于 C/C++,其中表达式中的类型确定运算的精度,而不是最终写入的类型。

测试最小精度着色器代码

参考光栅器 (D3D _ DRIVER _ TYPE _ REFERENCE) 通过量化每个 HLSL 指令到指定精度,大致了解 HLSL 着色器代码中最小精度的行为方式。 这有助于发现可能意外依赖超过最小精度的代码。 当 HLSL 着色器代码使用最小精度时,引用光栅器不会更快地运行,但可以使用它来验证代码的正确性。 WARP (D3D _ DRIVER _ TYPE _ WARP) 不支持在 HLSL 着色器代码中使用最小精度;WARP 仅以完全 32 位精度运行。

///

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值