解压缩和打包 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)
    
  4. 然后,应用程序可以使用所需的格式创建其他视图,例如 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 编程指南

HLSL 编程指南