2015-10-13 82 views
1

我正在計算着色器,其輸出寫入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 
    } 
+0

如果你一直的印象是'在GLSL中bool'是1個字節,你可能需要重新寫一些着色器:) –

+0

'#version 423 core' ... wat – genpfault

+0

@AndonM。Coleman我總是很高興揭示有關OpenGL新的陷阱:) –

回答

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); 
4

暴露在GPU上最小的類型往往是32位的標量。即使你提到的布爾類型實際上是32位。對於像C這樣的語言來說也是如此;一個布爾值不需要超過1位,但即使如此,bool也不是的同義詞「給我提供最小的數據類型」。

有內在功能,您可以使用,但是打包和解包的數據類型,我會告訴如何以下使用它們的例子:

#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); 

一些比特移位將是必要的正確包裝各成分,但這些都是微不足道的。

+0

好的答案,但打包可以打包到4個字節。而且我只需要每個條目一個字節。事實上,我找到了解決方案 - TBO.Partially.It只解決了我寫入字節的線性緩衝區的問題。但是它在CUDA方面出現了問題,因爲NVENC似乎不支持TBO的資源映射。 –

+0

我對這個評論錯了 - NVENC確實支持TBO。 –

相關問題