如何在 HLSL 中处理 8 位字符数据?

问题描述 投票:0回答:2

我正在将一些 OpenCL 代码转换为 DirectCompute,并且需要在计算着色器中处理 8 位字符串,但找不到“byte”或“char”的 HLSL 数据类型。 OpenCL 支持“char”类型,所以我期待一个等效的类型。定义和访问数据的最佳方式是什么?

似乎可以通过将数据视为一系列“uint”类型并使用位移位、与运算等解包来传递数据,但这似乎会导致不必要的开销。正确的做法是什么?

hlsl directcompute
2个回答
4
投票

我找到了两种方法来做到这一点,尽管它们都需要在 HLSL 中使用 int/uint 值,因为我还没有找到 8 位数据类型:

选项 1 是让“视图”处理翻译:

  • 将原始数据作为字节/字符缓冲区传递。
  • 将着色器资源视图格式(D3D11_SHADER_RESOURCE_VIEW_DESC.Format)设置为DXGI_FORMAT_R8_UINT
  • 将 HLSL 数据类型定义为
    Buffer<uint>
  • 使用字节偏移量引用每个字节(即,将其视为字节缓冲区而不是 uint 缓冲区)。每个字符都是 自动提升为 uint 值。

选项 2 是将每个 4 字节序列视为一个 uint,使用格式 DXGI_FORMAT_R32_UINT,并使用如下方式手动提取每个字符:

Buffer<uint> buffer;
uint offset = ...;    
uint ch1, ch2, ch3, ch4;
ch1 =  buffer[offset] >> 24;
ch2 = (buffer[offset] & 0x00ff0000) >> 16;
ch3 = (buffer[offset] & 0x0000ff00) >> 8;
ch4 = (buffer[offset] & 0x000000ff);

无论哪种方式,您最终都会使用 32 位值,但至少它们对应于单个字符。


0
投票

您还可以使用ByteAddressBuffer,创建步幅为1的ByteAddressBuffer,将srv格式设置为DXGI_FORMAT_R8_UINT。

在Hlsl中,使用“Load”函数加载uint32数据,用0xFF000000屏蔽数据以获得前8位,最后位移到正确的位地址。

我在虚幻引擎中工作,这些是我的代码:

c++

create ByteAddressBuffer:
            MaskBufferRHI = RHICreateBuffer(DataLength * sizeof(uint8), BUF_Static | BUF_ByteAddressBuffer | BUF_ShaderResource, sizeof(uint8), ERHIAccess::SRVCompute, MaskCreateInfo); // MaskCreateInfo contain all the data I need.
create svr with uint8:
            RHICreateShaderResourceView(MaskBufferRHI, sizeof(uint8), PF_R8_UINT);


hlsl
define buffer:
            ByteAddressBuffer InMaskBuffer;
retrieve uint8 data to uint32:
            const uint InMask = (InMaskBuffer.Load(SomeID) & 0xFF000000) >> 24;

(load function fill uint32 InMask with 4 uint8 data in out buffer at once, we need to mask out those data.)
© www.soinside.com 2019 - 2024. All rights reserved.