2012-10-04 38 views
3

我看到一個問題,我得到的GLSL統一塊的大小錯誤。統一緩衝區,glGetActiveUniformBlockiv報告的大小

這是着色器中的塊:

uniform MaterialInfo { 
    vec3 Ka; 
    vec3 Ks;  
    vec3 Kd; 
}; 

然後將下面的代碼來製備我的均勻緩衝對象:

blockIndex = glGetUniformBlockIndex(program, "MaterialInfo"); 
if (blockIndex == -1) { 
    fprintf(stderr, "Could not bind uniform block\n"); 
} 

printf("Found blockindex materialinfo: %d\n", blockIndex); 

glGetActiveUniformBlockiv(program, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize); 
blockBuffer = (GLubyte *) malloc(blockSize); 
cout << "GLSL blocksize: " << blockSize << endl; 
cout << "sizeof glm::vec3 type: " << sizeof(mesh->Ka) << endl; 
cout << "sizeof 3 x glm::vec3 type: " << 3 * sizeof(mesh->Ka) << endl; 

的報告如下:

GLSL blocksize: 48 
sizeof glm::vec3 type: 12 
sizeof 3 x glm::vec3 type: 36 

總之,我期待GLSL的塊大小爲36,而不是48。GLSL中的vec3應該像我的glm :: vec3類型。

另請注意,我使用的是HD4000 beta驅動程序:OpenGL 4.0.0 Build 9.17.10.2792。我沒有機會在另一臺電腦上測試。 這是我誤解的東西嗎?回覆後

跟帖:

因此,在這種情況下,正確的方式提交我的GLM :: VEC3浮如下?

glGetUniformIndices(program, 3, namesMaterial, indices); 
glGetActiveUniformsiv(program, 3, indices, GL_UNIFORM_OFFSET, offset); 

memcpy(blockBuffer + offset[0], glm::value_ptr(mesh->Ka), 4 * sizeof(GLfloat)); 
memcpy(blockBuffer + offset[1], glm::value_ptr(mesh->Ks), 4 * sizeof(GLfloat)); 
memcpy(blockBuffer + offset[2], glm::value_ptr(mesh->Kd), 4 * sizeof(GLfloat)); 
+0

對齊?我敢打賭,這些vec3s正在被vec4s填補。 – genpfault

+0

他們爲什麼被填充? – toeplitz

回答

3

總之,我期待GLSL塊大小是36,不是48 VEC3在GLSL應該是一個浮動像我GLM :: VEC 3種。

爲什麼? OpenGL規範中沒有任何內容保證塊的大小。

或者至少不是定義一個統一的塊。

如果不提供proper memory layout qualifier,則默認使用shared。這使得實現可以在元素之間放置任何感覺舒適的填充。所以你不能假設3 vec3 s將會連續12個尺寸的float s。每個vec3將連續3個float s,但不能保證不會有填充。

如果你想有一個固定的,已知的,一致佈局均勻的塊,那麼你需要使用std140佈局。否則,你會得到實現給你的東西。 OpenGL規範詳細說明了std140元素佈局的規則。

當然,與std140佈局,該塊的大小將是48,因爲它焊盤所有vec3元素vec4秒。


在這種情況下

所以正確的方式提交我的GLM :: VEC3浮如下?

這是正確的,假設:

  1. memoryBlock或者是一個映射緩衝對象指針或東西你glBufferSubData
  2. 上傳您上傳到緩衝區前或的一個適當的偏移量(glBindBufferRange的統一塊的偏移量必須與GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT對齊)。
  3. mesh->Ka其實其實4做花車。否則,你從未分配的內存中複製。

我再次懇請停止查詢這個東西,使用std140佈局。當你這樣做時,你不必查詢偏移量或任何東西;您可以設計與所有硬件中的GLSL定義完全兼容的結構。

+0

感謝relpy。更新我的問題後續如何創建blockBuffer。這是正確的方法嗎?我要問的原因是,這有一個統一的塊時,但一旦我添加第二個統一塊,我得到崩潰,。 – toeplitz

+0

@toeplitz:堆棧溢出不會馬上耗盡數據庫空間。詢問關於不同(即使有點相關)問題的後續問題的方法是再次按「問題問題」按鈕。但是,我更新了我的回答,以評論你的問題。如果您需要幫助解決崩潰問題,您需要在顯示該代碼的位置詢問一個新問題。 –

3

許多的GPU墊每個統一是vec4尺寸:

看到這個implementation note從OpenGL的維基(重點煤礦):

實現注意事項:OpenGL實現允許拒絕着色器依賴於實現的原因。所以你可以通過你的推算減少有效的統一組件,並且由於統一的限制,仍然無法鏈接。這通常在硬件上最初是矢量硬件。 Pre GeForce 8xxx硬件和所有ATi硬件均提供此。在這種情況下,你應該假定每個單獨的制服都佔用4個組件,就像在D3D中一樣。這意味着「統一浮點」是4個組件,mat2x4是16個組件(每行是4個組件),但mat4x2是8個組件。