为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. 使用在上一方案中指定的适当无类型依赖格式以及所需的绑定标志(如 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。 D3DX_DXGIFormatConvert.inl 中提供的格式转换函数仅在你想要同时读取和写入纹理的 UAV 时才可能有用。

 

下面是 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-float> 转换。

 

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-float> 转换。

 

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-float> 转换。

 

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 编程指南