带字节的着色器存储缓冲区对象
Shader storage buffer object with bytes
我正在开发一个计算着色器,输出被写入 SSBO。现在,这个缓冲区的消费者是 CUDA,它希望它包含无符号的 bytes.I 目前看不到 find如何在 SSBO.With 纹理或图像中为每个索引写入一个字节的方式 规范化浮点数到无符号字节的转换由 OpenGL.For 示例处理 我可以附加内部格式为 R8 的纹理并按 [=23 存储字节=] SSBO.Does 不可能有这样的事情,这意味着除了 bool 数据类型外,SSBO 中的所有数字存储类型每个条目至少只能有 4 个字节?
实际上我希望能够做到以下几点:
计算着色器:
#version 430 core
layout (local_size_x = 8,local_size_y = 8 ) in;
struct SSBOBlock
{
byte mydata;
};
layout(std430,binding = BUFFER_OUTPUT) writeonly buffer bBuffer
{
SSBOBlock Ouput[];
} Out;
void main()
{
//..... Compute shader stuff...
//.......
Out.Ouput[globalIndex].mydata = val;//where val is normalized float
}
GPU 上公开的最小类型往往是 32 位标量。甚至您提到的布尔类型实际上也是 32 位的。像 C 这样的语言通常也是如此;布尔值不需要超过 1 位,但即使如此 bool
也不是 "give me the smallest data type available."
的同义词
但是,您可以使用一些内部函数来打包和解包数据类型,我将在下面展示如何使用它们的示例:
#version 420 core
layout (local_size_x = 8,local_size_y = 8 ) in;
struct SSBOBlock
{
uint mydata;
};
layout(std430,binding = BUFFER_OUTPUT) writeonly buffer bBuffer
{
SSBOBlock Ouput[];
} Out;
void main()
{
//..... Compute shader stuff...
//.......
Out.Output [globalIndex].mydata = packUnorm4x8 (val)
// where val is a 4-component unsigned normalized vector to pack into globalIndex
}
您的示例着色器显示尝试将单个标量写入 "byte" 数据类型,这是不可能的,您将不得不以某种方式修改它以使用引用打包组的索引4 个标量。在最坏的情况下,这可能意味着解包三个值,然后重新打包整个东西,只为了写一个标量。
此内部函数在 GL_ARB_shading_languge_packing
的扩展规范中进行了讨论,并且是 GL 4.2 及更高版本的核心。
即使您使用的是不支持该扩展的实现,扩展规范的文本中也会准确解释每个扩展的作用。 packUnorm4x8
的等效操作是:
uint fixed_val = round(clamp(float_val, 0, +1) * 255.0);
正确打包每个组件需要一些位移,但这些都是微不足道的。
我找到了一种在计算着色器中将无符号字节数据写入缓冲区的方法。Buffer texture job.It 基本上是带有缓冲区的图像纹理,因为 storage.This 我可以指定图像格式成为 R8,它允许我在缓冲区的每个索引上存储字节大小值。
GLuint _tbo_buffer,_tbo_tex;
glGenBuffers(1, &_tbo_buffer);
glBindBuffer(GL_TEXTURE_BUFFER, _tbo_buffer);
glBufferData(GL_TEXTURE_BUFFER, SCREEN_WIDTH * SCREEN_HEIGHT, NULL, GL_DYNAMIC_COPY);
glGenTextures(1, &_tbo_tex);
glBindTexture(GL_TEXTURE_BUFFER, _tbo_tex);
//attach the TBO to the texture:
glTexBuffer(GL_TEXTURE_BUFFER, GL_R8, _tbo_buffer);
glBindImageTexture(0, _tbo_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R8);
计算着色器:
#version 430 core
layout (local_size_x = 8,local_size_y = 8 ) in;
layout(binding=0) uniform sampler2D TEX_IN;
layout(r8) writeonly uniform imageBuffer mybuffer;
void main(){
vec2 texSize = vec2(textureSize(TEX_IN,0));
vec2 uv = vec2(gl_GlobalInvocationID.xy / texSize);
vec4 tex = texture(TEX_IN,uv);
uint globalIndex = gl_GlobalInvocationID.y * nThreads.x + gl_GlobalInvocationID.x;
//store only r:
imageStore(mybuffer,int(globalIndex),vec4(0.5,0,0,0));
}
然后我们可以在 CPU 上逐字节读取或映射到 CUDA 缓冲区资源:
GLubyte* ptr = (GLubyte*)glMapBuffer(GL_TEXTURE_BUFFER, GL_READ_ONLY);
我正在开发一个计算着色器,输出被写入 SSBO。现在,这个缓冲区的消费者是 CUDA,它希望它包含无符号的 bytes.I 目前看不到 find如何在 SSBO.With 纹理或图像中为每个索引写入一个字节的方式 规范化浮点数到无符号字节的转换由 OpenGL.For 示例处理 我可以附加内部格式为 R8 的纹理并按 [=23 存储字节=] SSBO.Does 不可能有这样的事情,这意味着除了 bool 数据类型外,SSBO 中的所有数字存储类型每个条目至少只能有 4 个字节?
实际上我希望能够做到以下几点:
计算着色器:
#version 430 core
layout (local_size_x = 8,local_size_y = 8 ) in;
struct SSBOBlock
{
byte mydata;
};
layout(std430,binding = BUFFER_OUTPUT) writeonly buffer bBuffer
{
SSBOBlock Ouput[];
} Out;
void main()
{
//..... Compute shader stuff...
//.......
Out.Ouput[globalIndex].mydata = val;//where val is normalized float
}
GPU 上公开的最小类型往往是 32 位标量。甚至您提到的布尔类型实际上也是 32 位的。像 C 这样的语言通常也是如此;布尔值不需要超过 1 位,但即使如此 bool
也不是 "give me the smallest data type available."
但是,您可以使用一些内部函数来打包和解包数据类型,我将在下面展示如何使用它们的示例:
#version 420 core
layout (local_size_x = 8,local_size_y = 8 ) in;
struct SSBOBlock
{
uint mydata;
};
layout(std430,binding = BUFFER_OUTPUT) writeonly buffer bBuffer
{
SSBOBlock Ouput[];
} Out;
void main()
{
//..... Compute shader stuff...
//.......
Out.Output [globalIndex].mydata = packUnorm4x8 (val)
// where val is a 4-component unsigned normalized vector to pack into globalIndex
}
您的示例着色器显示尝试将单个标量写入 "byte" 数据类型,这是不可能的,您将不得不以某种方式修改它以使用引用打包组的索引4 个标量。在最坏的情况下,这可能意味着解包三个值,然后重新打包整个东西,只为了写一个标量。
此内部函数在 GL_ARB_shading_languge_packing
的扩展规范中进行了讨论,并且是 GL 4.2 及更高版本的核心。
即使您使用的是不支持该扩展的实现,扩展规范的文本中也会准确解释每个扩展的作用。 packUnorm4x8
的等效操作是:
uint fixed_val = round(clamp(float_val, 0, +1) * 255.0);
正确打包每个组件需要一些位移,但这些都是微不足道的。
我找到了一种在计算着色器中将无符号字节数据写入缓冲区的方法。Buffer texture job.It 基本上是带有缓冲区的图像纹理,因为 storage.This 我可以指定图像格式成为 R8,它允许我在缓冲区的每个索引上存储字节大小值。
GLuint _tbo_buffer,_tbo_tex;
glGenBuffers(1, &_tbo_buffer);
glBindBuffer(GL_TEXTURE_BUFFER, _tbo_buffer);
glBufferData(GL_TEXTURE_BUFFER, SCREEN_WIDTH * SCREEN_HEIGHT, NULL, GL_DYNAMIC_COPY);
glGenTextures(1, &_tbo_tex);
glBindTexture(GL_TEXTURE_BUFFER, _tbo_tex);
//attach the TBO to the texture:
glTexBuffer(GL_TEXTURE_BUFFER, GL_R8, _tbo_buffer);
glBindImageTexture(0, _tbo_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R8);
计算着色器:
#version 430 core
layout (local_size_x = 8,local_size_y = 8 ) in;
layout(binding=0) uniform sampler2D TEX_IN;
layout(r8) writeonly uniform imageBuffer mybuffer;
void main(){
vec2 texSize = vec2(textureSize(TEX_IN,0));
vec2 uv = vec2(gl_GlobalInvocationID.xy / texSize);
vec4 tex = texture(TEX_IN,uv);
uint globalIndex = gl_GlobalInvocationID.y * nThreads.x + gl_GlobalInvocationID.x;
//store only r:
imageStore(mybuffer,int(globalIndex),vec4(0.5,0,0,0));
}
然后我们可以在 CPU 上逐字节读取或映射到 CUDA 缓冲区资源:
GLubyte* ptr = (GLubyte*)glMapBuffer(GL_TEXTURE_BUFFER, GL_READ_ONLY);