2016-05-15 5 views
2

NBidiaのサンプルプロジェクトgl_commandlist_basicで、glBindBufferRangeのオフセット/アライメントがどのように機能するのかを理解できません。 私はオフセットが256のGL_UNIFORM_BUFFER_OFFSET_ALIGNMENTの倍数である必要があること、および/またはglBindBufferの範囲でオフセットとアラインメントが非常に重要であることを読んだことがあります。。私はmat4/vec4で動作するサンプルUBOと、mat4/mat3/vec4で動作しないサンプルを持っています。どちらの場合も、UBOは256の倍数になることはありません。私はvec4(0.f、1.f、0.f、1.f)を送信しようとしています。なぜ私のglBindBufferRangeオフセットの配置が間違っていますか?

mat4 = 64バイト、mat3 = 36バイト、vec4 = 16バイトの場合、動作例は64 + 16 = 80バイトで、は256の倍数ではありません。動作していない例は64 + 36 + 16 = 116バイトです。

NVは、作業/非からこれを削除

inline size_t uboAligned(size_t size) { return ((size + 255)/256) * 256; } 

として定義された差のいずれかの方法を作っていないをuboAligned と呼ばれるインラインを使用します。

float/vec2/vec3/vec4などの形でUBOに「パディング」を追加する必要があると仮定します。mat4を使用する場合に必要なパディングの正確な量を決定するにはどうすればよいですか/ mat3/vec4 UBO?

/* APPLICATION */ 
typedef struct 
{ 
    glm::mat4 MM; 
    // glm::mat3 NM; 
    glm::vec4 Cs; 
} myData0; 

Gluint objectUBO; 
glCreateBuffers(1, &objectUBO); 
glNamedBufferData(objectUBO, uboAligned(sizeof(abjObjectData) * 2), 0, GL_STATIC_DRAW); // 

for (unsigned int i = 0; i < allObj.size(); ++i) 
{ 
    myData0 myDataTemp; 
    myDataTemp.Cs = glm::vec4(0.f, 1.f, 0.f, 1.f); 
    glNamedBufferSubData(objectUBO, sizeof(abjObjectData) * i, sizeof(abjObjectData), &objDataInit); 
} 

//hot loop 
for (unsigned int i = 0; i < allObj.size(); ++i) 
{ 
    glBindBufferRange(GL_UNIFORM_BUFFER, 1, objectUBO, uboAligned(sizeof(abjObjectData)) * i, sizeof(abjObjectData)); 
    //draw 
} 

/* HW */ 
out vec4 Ci; 

struct ObjectData 
{ 
    mat4 MM; 
    // mat3 NM; 
    vec4 Cs; 
}; 

layout (std140, binding = 1) uniform objectBuffer { ObjectData object; }; 

void main() 
{ 
    Ci = object.Cs; 
} 
+0

"*これを作業中から削除するとどちらにも違いはありません。*"どのくらい削除しましたか?あなたは何を関数に返すようにしましたか? –

+0

もし私がUBOでvec4を送るだけなら、2番目のオブジェクトのuboAligned()オフセットは256になり、シェーダの値は読み込まれませんが、uboAligned()がなければオフセットは16になります。 ..もし私が手作業でUBOに240ビットの余分なデータを書き込むと、それは読み込まれます。しかし、いくつかのパディングを持つNVの例は「最大256まで加算されません。」オフセット/パディングが混乱するのは混乱します(?)GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT – waaitt

答えて

1

glNamedBufferDataを使用した単純なタイプミス。

glNamedBufferData(objectUBO, uboAligned(sizeof(abjObjectData)) * 2, 0, GL_STATIC_DRAW); 

修正オフセット/位置合わせの問題に

glNamedBufferData(objectUBO, uboAligned(sizeof(abjObjectData) * 2), 0, GL_STATIC_DRAW); 

から変更。

-2

OpenGLは特定の配置を使用します。

struct PointLight 
{ 
    glm::vec3 position; 
    int padding; //this is needed for alignement 
    glm::vec3 color; // because a vec3 has to be aligned 
    float intensity; //no need for alignment because a float can be read directly without alignement 
}; 

あなたがシェーダで、このような構造体の均一化に渡すことができます:例えば、これはCPPで定義された構造であり、あなたがstd140レイアウトを使用していると仮定すると、

uniform light 
{ 
    vec3 Position; 
    vec3 Color; 
    float Intensity; 
} PointLight; 

私がテストします以下のようなもの:

struct ObjectData 
{ 
    mat4 MM; 
    mat3 NM; 
    vec3 padding; //I think you have to add 3 floats of padding 
    vec4 Cs; 
}; 

しかし、私は、私が最初の場所でそれを見つけた私は覚えていない、それをもっとに関する情報を見つけることができませんでした。

あなたはそれらを確認することができます、あなたはそれらを確認することができます、hereの仕様でメモリレイアウトを定義し、私はこのレイアウトを使用することをお勧めします。そうしないと、共有レイアウトが使用され、レイアウトをクエリする必要があります。 OpenGLを使用してレイアウトを照会して、追加する必要のあるパディングを知ることができますBlockLayoutQuery

glBindBufferRangeに関して、私は256ビット配列について聞いたことがありません。ここで私はそれを使用する方法の例です:

const int pointLightCount = SomeNumber; 
int pointLightBufferSize = sizeof(PointLight) * pointLightCount + sizeof(int) * 4; 

glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[0]); 
glBufferData(GL_SHADER_STORAGE_BUFFER, pointLightBufferSize, 0, GL_DYNAMIC_COPY); 
void * lightBuffer = glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY); 
((int*) lightBuffer)[0] = pointLightCount; 
for (int i = 0; i < pointLightCount; ++i) { 
     PointLight p = { something }; 
     ((PointLight*) ((int*) lightBuffer + 4))[i] = p; 
    } 
    glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); 
    glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, ssbo[0], 0, pointLightBufferSize); //Bind all the buffer 
+0

実際、私はスワップを修正しました。私はレイアウトstd140とglBindBufferRangeについて書いていましたが、書いている間違いだけでした。 – Toffanim

関連する問題