Ich habe etwas mit GL3.3 geschrieben, das einen einheitlichen Puffer benötigt, und nutzt die Informationen, um Sprite-Kacheln in einem Frag-Shader auszuwählen. Es funktioniert auf meinem Desktop mit einer Nvidia GTX780, aber mein AMD-basierter Laptop (A6-4455M) hat einige Probleme damit. Beide sind auf den neuesten (oder sehr aktuellen) Treibern.Einheitliche gepufferte Array-Elemente sind falsch
Zurück zum Code, Es richtet zunächst einen einheitlichen Puffer ein, der aus zwei uints und einem uint-Array besteht. Sie werden dann gefüllt und im Shader aufgerufen. Zuerst bekam ich einen GL-Fehler auf dem Laptop, weil ich nicht genug zuzuteilen, aber eine temporäre Änderung, die Padding berücksichtigt, hat das aussortiert, und jetzt werden Daten tatsächlich gepuffert.
Die ersten beiden sind kein Problem. Ich habe auch das Array im Shader etwas lesbar, es gibt nur ein Problem; Die Daten werden mit vier multipliziert! Im Moment ist das Array nur ein paar Testdaten, die auf seinen Index initialisiert wurden, also spriteArr [1] == 1, spriteArr [34] == 34, etc. Allerdings gibt spriteArr [10] im Shader darauf hin 40. Das geht bis zu spriteArr [143] == 572. Darüber hinaus und es ist etwas anderes. Ich weiß nicht genau, warum das so ist, aber es scheint ein falscher Offset zu sein.
Ich verwende das gemeinsame einheitliche Layout und die Uniform Offsets von GL selbst, so dass sie korrekt sein sollten. Ich habe bemerkt, dass die Offsets auf der AMD-Karte viel größer sind, als wenn sie mehr Padding hinzufügen würde. Sie sind immer 0,4,8 auf dem Desktop, aber 0,16,32 auf dem Laptop.
Wenn es einen Unterschied macht, gibt es einen anderen UBO (Bindungspunkt 0), der für die Ansichts- und Projektionsmatrizen verwendet wird. Diese funktionieren wie beabsichtigt. Es wird jedoch nicht im Fragment-Shader verwendet. Es wird auch vor diesem UBO erstellt.
UBO Initialisierungscode:
GLuint spriteUBO;
glGenBuffers(1, &spriteUBO);
glBindBuffer(GL_UNIFORM_BUFFER, spriteUBO);
unsigned maxsize = (2 + 576 + 24) * sizeof(GLuint);
/*Bad I know, but temporary. AMD's driver adds 24 bytes of padding. Nvidias has none.
Not the cause of this problem. At least ensures we have enough allocated. */
glBufferData(GL_UNIFORM_BUFFER, maxsize, NULL, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
//Set binding point
GLuint spriteUBOIndex = glGetUniformBlockIndex(programID, "SpriteMatchData");
glUniformBlockBinding(programID, spriteUBOIndex, 1);
static const GLchar *unames[] =
{
"width", "height",
//"size",
"spriteArr"
};
GLuint uindices[3];
GLint offsets[3];
glGetUniformIndices(programID,3,unames,uindices);
glGetActiveUniformsiv(programID, 3, uindices, GL_UNIFORM_OFFSET, offsets);
//buffer stuff
glBindBufferBase(GL_UNIFORM_BUFFER, 1, spriteUBO);
glBufferSubData(GL_UNIFORM_BUFFER,offsets[0], sizeof(GLuint), tm.getWidth());
glBufferSubData(GL_UNIFORM_BUFFER, offsets[1], sizeof(GLuint), tm.getHeight());
glBufferSubData(GL_UNIFORM_BUFFER, offsets[2], tm.getTileCount() * sizeof(GLuint), tm.getSpriteArray());
Fragment Shader:
layout (shared) uniform SpriteMatchData{
uint width, height;
uint spriteArr[576];};
Dann später ich mit so etwas wie dies mit dem Array experimentieren:
if(spriteArr[10] == uint(40))
{
debug_colour = vec4(0.0,1.0,0.0,0.0);//green
}
else
{
debug_colour = vec4(1.0,0.0,0.0,0.0); //red
}
Mit debug_colour grün Drehen in diese Instanz.
Gibt es eine Möglichkeit, dies mit etwas zu lösen, das mit beiden Systemen funktioniert? Warum geht der AMD Treiber so anders damit um? Könnte es sich um einen Fehler in der Art und Weise handeln, wie es mit uniformen UInt-Arrays umgeht?
Danke, ich überprüfe die Array-Schritte in ein bisschen, ich vergaß diese und automatisch angenommen, dass sie korrekt sein würden. Es scheint so, als könnte das das Problem sein. – Teaplusplus
Nur einen kurzen Test gemacht, und ja, die Schritte sind anders. 4 auf dem Desktop und 16 auf dem Laptop, was zu dem passt, was ich bekomme. Ich nehme an, der Standard-Array-Schritt ist mehr für Arrays von vec4s als uints eingerichtet. Ich habe std140 nicht früher benutzt, weil ich ein Problem damit hatte, aber ich werde es jetzt noch einmal versuchen. Ich weiß, dass es wahrscheinlich mit dem Array-Schritt zusammenhängt oder nicht genug Platz für seine zusätzliche Auffüllung zuweist. – Teaplusplus