具有字节

时间:2015-10-13 09:17:28

标签: opengl glsl compute-shader

我正在研究一个计算着色器,其中输出被写入SSBO。现在,这个缓冲区的消费者是CUDA,它希望它包含无符号字节。我目前看不到如何找到方法在SSBO中为每个索引写一个字节。对于纹理或图像,规范化的浮点数到无符号字节转换由OpenGL处理​​。例如,我可以附加一个内部格式为R8的纹理,并为每个条目存储字节。但是SSBO可以做到这一点。这是否意味着除了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
   }

2 个答案:

答案 0 :(得分:4)

暴露在GPU上的最小类型对于标量来说往往是32位。甚至你提到的布尔类型实际上是32位。对于像C这样的语言来说也是如此;布尔值不需要超过1位,但即便如此,bool也不是&#34的同义词;给我最小的数据类型。"

然而,您可以使用内部函数来打包和解压缩数据类型,我将在下面展示如何使用它们的示例:

#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
}

您的样本着色器显示尝试将单个标量写入"字节"数据类型,这是不可能的,你将不得不以某种方式修改它以使用引用4个标量的压缩组的索引。在最坏的情况下,这可能意味着解压缩三个值,然后重新打包整个东西只是为了写一个标量。

此内在函数在GL_ARB_shading_languge_packing的扩展规范中讨论,并且是GL 4.2及更高版本的核心。

即使您使用的是不支持该扩展的实现,也会在扩展规范的文本中对其进行详细说明。 packUnorm4x8的等效操作是:

uint fixed_val = round(clamp(float_val, 0, +1) * 255.0);

正确包装每个组件需要一些位移,但这些都是微不足道的。

答案 1 :(得分:0)

我找到了一种在计算着色器中将无符号字节数据写入缓冲区的方法。Buffer texture完成工作。它基本上是带有缓冲区作为存储的图像纹理。这样我可以将图像格式指定为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);