-
Notifications
You must be signed in to change notification settings - Fork 39
Description
Hi,
It's been a long time since I started chasing a bug with Shader Storage Buffer Object: if I use a mix of UBOs and SSBOs, sometimes nothing would show up in the window.
I suspect that somehow bindBuffersToCurrentRenderEncoder uses a wrong index or offset value: using the loop increment seems to be suspect to me, but I may be completely wrong. Besides, BufferMap::buffer_base_index and Buffer::index are set, but never used, which seems suspect too.
I tried various combinations of indexand offset with setVertexBuffer:offset:atIndex: to no avail.
I could finally edit test_2D_textures to replicate it (below). This version does not work. To make it work, turn the SSBO back to a UBO (there are 3 lines of code to change, all prefixed with // BUG:). Other combinations of SSBO and UBO do work, the bug might be due to how SPIRV arranges the order of the table entries in a first place (?) (see spirv log below).
@guymadison I figured that you could have a look at it and try to fix it? You may be much faster than me...
[EDIT] I suspect this is at the root of other bugs such as this one. This may be a showstopper for any moderately complex shaders. I could be wrong of course.
[EDIT2] I could find why it's buggy: in the vertex shader below, scale is not used, hence spvc-cross does not emit anything for its buffer. Setting the buffer will thus overwrite the next one... if scale is used (e.g. multiply the coordinates with it and a 1.0 value), everything is ok. So we need to know which buffer is actually used, and not send it in bindBuffersToCurrentRenderEncoder if it's not... And I do not know how to do that.
int test_2D_textures(GLFWwindow* window, int width, int height)
{
GLuint vbo = 0, col_vbo = 0, tex_vbo = 0, mat_ubo = 0, scale_ubo = 0, col_att_ubo = 0;
const char* vertex_shader =
GLSL(450 core,
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 in_color;
layout(location = 2) in vec2 in_texcords;
layout(location = 0) out vec4 out_color;
layout(location = 1) out vec2 out_texcoords;
layout(binding = 0)
//uniform // BUG: uncomment this to make it work
readonly buffer // BUG: comment this to make it work
matrices
{
mat4 rotMatrix;
};
layout(binding = 1)
uniform
//readonly buffer
scale
{
float pos_scale;
};
void main() {
gl_Position = rotMatrix * vec4(position, 1.0);
out_color = vec4(in_color, 1.0);
out_texcoords = in_texcords;
}
);
const char* fragment_shader =
GLSL(450 core,
layout(location = 0) in vec4 in_color;
layout(location = 1) in vec2 in_texcords;
layout(location = 0) out vec4 frag_colour;
layout(binding = 2)
uniform
//readonly buffer
color_att
{
float att;
};
uniform sampler2D image;
void main() {
vec4 tex_color = texture(image, in_texcords);
// frag_colour = in_color * att;
frag_colour = in_color * att * tex_color;
//frag_colour = tex_color;
}
);
float points[] = {
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f
};
float color[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
};
float texcoords[] = {
0.5f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &col_vbo);
glBindBuffer(GL_ARRAY_BUFFER, col_vbo);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), color, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &tex_vbo);
glBindBuffer(GL_ARRAY_BUFFER, tex_vbo);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), texcoords, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//GL_UNIFORM_BUFFER;
//GL_SHADER_STORAGE_BUFFER;
GLenum mat_target = GL_SHADER_STORAGE_BUFFER; // BUG: replace with GL_UNIFORM_BUFFER to make it work
GLenum scale_target = GL_UNIFORM_BUFFER;
GLenum col_target = GL_UNIFORM_BUFFER;
mat4 rotZ = glm::identity<mat4>();
float angle = M_1_PI / 6;
rotZ = glm::rotate(glm::identity<mat4>(), angle, glm::vec3(0, 0, 1));
glGenBuffers(1, &mat_ubo);
glBindBuffer(mat_target, mat_ubo);
glBufferData(mat_target, sizeof(mat4),&rotZ[0][0], GL_STATIC_DRAW);
glBindBuffer(mat_target, 0);
float scale = -1.0;
glGenBuffers(1, &scale_ubo);
glBindBuffer(scale_target, scale_ubo);
glBufferData(scale_target, sizeof(float), &scale, GL_STATIC_DRAW);
glBindBuffer(scale_target, 0);
float att = 1.0;
glGenBuffers(1, &col_att_ubo);
glBindBuffer(col_target, col_att_ubo);
glBufferData(col_target, sizeof(float), &att, GL_STATIC_DRAW);
glBindBuffer(col_target, 0);
GLuint vao = 0;
glCreateVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, col_vbo);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, tex_vbo);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, NULL);
// clear currently bound buffer
glBindBuffer(GL_ARRAY_BUFFER, 0);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);
GLuint shader_program = glCreateProgram();
glAttachShader(shader_program, fs);
glAttachShader(shader_program, vs);
glLinkProgram(shader_program);
glUseProgram(shader_program);
// GLuint matrices_loc = glGetUniformBlockIndex(shader_program, "matrices");
// assert(matrices_loc == 0);
// GLuint scale_loc = glGetUniformBlockIndex(shader_program, "scale");
// assert(scale_loc == 1);
// GLuint color_att_loc = glGetUniformBlockIndex(shader_program, "color_att");
// assert(color_att_loc == 2);
glBindBufferBase(mat_target, 0, mat_ubo);
glBindBufferBase(scale_target, 1, scale_ubo);
glBindBufferBase(col_target, 2, col_att_ubo);
glActiveTexture(GL_TEXTURE0);
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE,
genTexturePixels(GL_RGBA, GL_UNSIGNED_BYTE, 0x10, 256,256));
// GLuint tex2;
// glGenTextures(1, &tex2);
// glBindTexture(GL_TEXTURE_2D, tex2);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE,
// genTexturePixels(GL_RGBA, GL_UNSIGNED_BYTE, 0x10, 256,512));
glViewport(0, 0, width, height);
glBindVertexArray(vao);
glUseProgram(shader_program);
glClearColor(0.2, 0.2, 0.2, 0.0);
float att_delta = 0.01;
while (!glfwWindowShouldClose(window))
{
//GLsync sync;
glClear(GL_COLOR_BUFFER_BIT);
// glBindTexture(GL_TEXTURE_2D, tex2);
// glDrawArrays(GL_TRIANGLES, 0, 3);
glBindTexture(GL_TEXTURE_2D, tex);
glDrawArrays(GL_TRIANGLES, 0, 3);
//sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
SWAP_BUFFERS;
angle += (M_PI / 180);
rotZ = glm::rotate(glm::identity<mat4>(), angle, glm::vec3(0, 0, 1));
//glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
glBindBuffer(mat_target, mat_ubo);
glBufferSubData(mat_target, 0, sizeof(mat4), &rotZ[0][0]);
glBindBuffer(mat_target, 0);
att += att_delta;
if (att > 1.0)
{
att = 1.0;
att_delta *= -1.0;
}
else if (att < 0.0)
{
att = 0.0;
att_delta *= -1.0;
}
glBindBuffer(col_target, col_att_ubo);
glBufferSubData(col_target, 0, sizeof(float), &att);
glBindBuffer(col_target, 0);
glfwPollEvents();
}
return 0;
}
Not working:
res_type: UNIFORM_BUFFER ID: 50 BaseTypeID: 48 TypeID: 49 Name: scale Set: 0 Binding: 1 Location: 0 Index: 0 Uniform: 0
res_type: STORAGE_BUFFER ID: 19 BaseTypeID: 17 TypeID: 18 Name: matrices Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0
res_type: STAGE_INPUT ID: 25 BaseTypeID: 23 TypeID: 24 Name: position Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0
res_type: STAGE_INPUT ID: 36 BaseTypeID: 23 TypeID: 24 Name: in_color Set: 0 Binding: 0 Location: 1 Index: 0 Uniform: 0
res_type: STAGE_INPUT ID: 46 BaseTypeID: 42 TypeID: 45 Name: in_texcords Set: 0 Binding: 0 Location: 2 Index: 0 Uniform: 0
res_type: STAGE_OUTPUT ID: 35 BaseTypeID: 7 TypeID: 33 Name: out_color Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0
res_type: STAGE_OUTPUT ID: 44 BaseTypeID: 42 TypeID: 43 Name: out_texcoords Set: 0 Binding: 0 Location: 1 Index: 0 Uniform: 0
res_type: UNIFORM_BUFFER ID: 27 BaseTypeID: 25 TypeID: 26 Name: color_att Set: 0 Binding: 2 Location: 0 Index: 0 Uniform: 0
res_type: STAGE_INPUT ID: 17 BaseTypeID: 15 TypeID: 16 Name: in_texcords Set: 0 Binding: 0 Location: 1 Index: 0 Uniform: 0
res_type: STAGE_INPUT ID: 23 BaseTypeID: 7 TypeID: 22 Name: in_color Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0
res_type: STAGE_OUTPUT ID: 21 BaseTypeID: 7 TypeID: 20 Name: frag_colour Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0
res_type: SAMPLED_IMAGE ID: 13 BaseTypeID: 11 TypeID: 12 Name: image Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0
Working: (all UBOs):
res_type: UNIFORM_BUFFER ID: 19 BaseTypeID: 17 TypeID: 18 Name: matrices Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0
res_type: UNIFORM_BUFFER ID: 50 BaseTypeID: 48 TypeID: 49 Name: scale Set: 0 Binding: 1 Location: 0 Index: 0 Uniform: 0
res_type: STAGE_INPUT ID: 25 BaseTypeID: 23 TypeID: 24 Name: position Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0
res_type: STAGE_INPUT ID: 36 BaseTypeID: 23 TypeID: 24 Name: in_color Set: 0 Binding: 0 Location: 1 Index: 0 Uniform: 0
res_type: STAGE_INPUT ID: 46 BaseTypeID: 42 TypeID: 45 Name: in_texcords Set: 0 Binding: 0 Location: 2 Index: 0 Uniform: 0
res_type: STAGE_OUTPUT ID: 35 BaseTypeID: 7 TypeID: 33 Name: out_color Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0
res_type: STAGE_OUTPUT ID: 44 BaseTypeID: 42 TypeID: 43 Name: out_texcoords Set: 0 Binding: 0 Location: 1 Index: 0 Uniform: 0
res_type: UNIFORM_BUFFER ID: 27 BaseTypeID: 25 TypeID: 26 Name: color_att Set: 0 Binding: 2 Location: 0 Index: 0 Uniform: 0
res_type: STAGE_INPUT ID: 17 BaseTypeID: 15 TypeID: 16 Name: in_texcords Set: 0 Binding: 0 Location: 1 Index: 0 Uniform: 0
res_type: STAGE_INPUT ID: 23 BaseTypeID: 7 TypeID: 22 Name: in_color Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0
res_type: STAGE_OUTPUT ID: 21 BaseTypeID: 7 TypeID: 20 Name: frag_colour Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0
res_type: SAMPLED_IMAGE ID: 13 BaseTypeID: 11 TypeID: 12 Name: image Set: 0 Binding: 0 Location: 0 Index: 0 Uniform: 0