用于In-Place图像编辑的解压缩和打包DXGI_FORMAT

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

D3DX_DXGIFormatConvert.inl 标头随附在旧版 DirectX SDK 中。 它还包含在 Microsoft.DXSDK.D3DX NuGet包中。

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

但是,只要资源的原始格式支持强制转换为DXGI_FORMAT_R32_UINT,你仍然可以同时读取和写入此类其他格式,方法是在创建 UAV 时将纹理强制转换为DXGI_FORMAT_R32_UINT纹理格式。 每个元素的大多数 32 位格式都支持转换为DXGI_FORMAT_R32_UINT。 通过在创建 UAV 时将纹理强制转换为DXGI_FORMAT_R32_UINT纹理格式,那么只要着色器在读取和写入时对读取和打包执行手动格式打包,就可以同时执行对纹理的读取和写入操作。

将纹理强制转换为DXGI_FORMAT_R32_UINT纹理格式的好处是,稍后可以使用适当的格式 (,例如,在同一纹理上与其他视图DXGI_FORMAT_R16G16_FLOAT) ,例如呈现目标视图 (RTV) 或 SRV。 因此,硬件可以执行典型的自动格式解压缩和打包,可以执行纹理筛选,等等,其中没有硬件限制。

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

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

  • DXGI_FORMAT_R10G10B10A2_TYPELESS
  • DXGI_FORMAT_R8G8B8A8_TYPELESS
  • DXGI_FORMAT_B8G8R8A8_TYPELESS
  • DXGI_FORMAT_B8G8R8X8_TYPELESS
  • DXGI_FORMAT_R16G16_TYPELESS

例如,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_RESOURCE。

  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_FORMAT进行分类。 每个受支持的格式都从上述方案中列出的 TYPELESS 格式之一下降,并支持转换为 UAV DXGI_FORMAT_R32_UINT。

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 类型函数使用没有足够精度的着色器指令来给出确切答案。 备用函数使用存储在着色器中的查阅表来提供精确的 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_FORMAT_B8G8R8A8_UNORM

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

DXGI_FORMAT_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 类型函数使用没有足够精度的着色器指令来给出确切答案。 备用函数使用存储在着色器中的查阅表来提供精确的 SRGB 浮>点转换。

 

DXGI_FORMAT_B8G8R8X8_UNORM

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

DXGI_FORMAT_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 类型函数使用没有足够精度的着色器指令来给出确切答案。 备用函数使用存储在着色器中的查阅表来提供精确的 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 编程指南