[Piglit] [PATCH] max-samplers: use the maximum number of textures in every shader
Marek Olšák
maraeo at gmail.com
Wed May 8 18:27:30 PDT 2013
On Thu, May 9, 2013 at 1:16 AM, Brian Paul <brianp at vmware.com> wrote:
>> +static const char *vs_source =
>> + "#define NUM %i \n"
>> + "uniform sampler2D vertex_tex[NUM]; \n"
>> + "uniform int vertex_index;"
>> + "varying vec3 vertex_tex_color; \n"
>> + "void main() \n"
>> + "{ \n"
>> + " int i; \n"
>> + " gl_Position = gl_Vertex; \n"
>> + " vertex_tex_color = vec3(0.0); \n"
>> + " for (i = 0; i< NUM; i++) \n"
>> + " if (i == vertex_index) \n"
>> + " vertex_tex_color =
>> texture2DLod(vertex_tex[i], vec2(0.5), 0.0).xyz; \n"
>> + "} \n";
>
>
> Does this loop (and the fs loop below) get unrolled now with Mesa?
>
> I think variable indexing of sampler uniforms is sometimes trouble to
> implement. I wouldn't be surprised if an OpenGL driver failed this test
> because of that. I wrote the mesa-demos/src/glsl/samplers.c test to
> exercise this a long time ago.
>
> With a bit of work, the shader code could be generated without the loop.
> But I'm OK with it as-is until we find a need to change it.
I didn't use variable indexing of sampler uniforms on purpose, because
it wasn't what I was going for with this test. Yes, the loops get
unrolled.
>
>
>> +
>> +static const char *vs_source_no_textures =
>> + "varying vec3 vertex_tex_color; \n"
>> + "void main() \n"
>> + "{ \n"
>> + " gl_Position = gl_Vertex; \n"
>> + " vertex_tex_color = vec3(0.0); \n"
>> + "} \n";
>> +
>> +static const char *fs_source =
>> + "#define NUM %i \n"
>> + "uniform sampler2D fragment_tex[NUM]; \n"
>> + "uniform int fragment_index;"
>> + "varying vec3 vertex_tex_color; \n"
>> + "void main() \n"
>> + "{ \n"
>> + " int i; \n"
>> + " vec3 fragment_tex_color = vec3(0.0); \n"
>> + " for (i = 0; i< NUM; i++) \n"
>> + " if (i == fragment_index) \n"
>> + " fragment_tex_color =
>> texture2D(fragment_tex[i], vec2(0.5), 0.0).xyz; \n"
>> + " gl_FragColor = vec4(fragment_tex_color + vertex_tex_color,
>> 1.0); \n"
>> + "} \n";
>> +
>> +GLuint prog;
>> +static int max_vs_textures, max_fs_textures;
>> +
>> +static void
>> +get_texture_color(int unit, float out[3])
>> +{
>> + out[0] = (unit % 16) / 15.0;
>> + out[1] = (unit / 16) / 15.0;
>> + out[2] = 0;
>> +}
>> +
>> +static void
>> +set_uniform(GLuint prog, const char *name, int value)
>> +{
>> + GLuint loc = glGetUniformLocation(prog, name);
>> + if (loc != -1)
>> + glUniform1i(loc, value);
>> +}
>> +
>> +static GLvoid
>> +draw_rect_core(int ix, int iy, int iw, int ih)
>> +{
>> + float x = -1 + 2.0*ix/piglit_width;
>> + float y = -1 + 2.0*iy/piglit_height;
>> + float w = 2.0*iw/piglit_width;
>> + float h = 2.0*ih/piglit_height;
>> + float verts[4][4];
>> + GLuint vbo;
>> +
>> + verts[0][0] = x;
>> + verts[0][1] = y;
>> + verts[0][2] = 0.0;
>> + verts[0][3] = 1.0;
>> + verts[1][0] = x + w;
>> + verts[1][1] = y;
>> + verts[1][2] = 0.0;
>> + verts[1][3] = 1.0;
>> + verts[2][0] = x + w;
>> + verts[2][1] = y + h;
>> + verts[2][2] = 0.0;
>> + verts[2][3] = 1.0;
>> + verts[3][0] = x;
>> + verts[3][1] = y + h;
>> + verts[3][2] = 0.0;
>> + verts[3][3] = 1.0;
>> +
>> + glGenBuffers(1,&vbo);
>> + glBindBuffer(GL_ARRAY_BUFFER, vbo);
>> + glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts,
>> GL_STATIC_DRAW);
>> +
>> + glEnableVertexAttribArray(0);
>> + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
>> +
>> + glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
>> +
>> + glDisableVertexAttribArray(0);
>> + glDeleteBuffers(1,&vbo);
>> +}
>> +
>> +static GLboolean
>> +probe_pixel(int unit, int x, int y)
>> +{
>> + float expected[3];
>> +
>> + get_texture_color(unit, expected);
>> +
>> + if (piglit_probe_pixel_rgb(x, y, expected))
>> + return GL_TRUE;
>> +
>> + printf(" When testing texture unit %i\n", unit);
>> + return GL_FALSE;
>> +}
>> +
>> +enum piglit_result
>> +piglit_display(void)
>> +{
>> + GLboolean pass = GL_TRUE;
>> + int i, unit, x, y;
>> +
>> + glClear(GL_COLOR_BUFFER_BIT);
>> +
>> + x = 0;
>> + y = 0;
>> + unit = 0;
>> +
>> + set_uniform(prog, "fragment_index", max_fs_textures);
>> + for (i = 0; i< max_vs_textures; i++) {
>> + set_uniform(prog, "vertex_index", i);
>> + draw_rect_core(x, y, 20, 20);
>> + pass = probe_pixel(unit, x+10, y+10)&& pass;
>>
>> +
>> + unit++;
>> + x += 20;
>> + if (x+20> piglit_width) {
>> + x = 0;
>> + y += 20;
>> + }
>> + }
>> +
>> + set_uniform(prog, "vertex_index", max_vs_textures);
>> + for (i = 0; i< max_fs_textures; i++) {
>> + set_uniform(prog, "fragment_index", i);
>> + draw_rect_core(x, y, 20, 20);
>> + pass = probe_pixel(unit, x+10, y+10)&& pass;
>>
>> +
>> + unit++;
>> + x += 20;
>> + if (x+20> piglit_width) {
>> + x = 0;
>> + y += 20;
>> + }
>> + }
>> +
>> + piglit_check_gl_error(GL_NO_ERROR);
>> + piglit_present_results();
>> +
>> + return pass ? PIGLIT_PASS : PIGLIT_FAIL;
>> +}
>> +
>> +static void
>> +set_texture(int unit)
>> +{
>> + GLuint tex;
>> + float color[3];
>> +
>> + get_texture_color(unit, color);
>> +
>> + glGenTextures(1,&tex);
>> + glActiveTexture(GL_TEXTURE0 + unit);
>> + glBindTexture(GL_TEXTURE_2D, tex);
>> + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0,
>> + GL_RGB, GL_FLOAT, color);
>> + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
>> + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
>> +
>> + piglit_check_gl_error(GL_NO_ERROR);
>> +}
>> +
>> +void
>> +piglit_init(int argc, char **argv)
>> +{
>> + GLuint vs, fs, vao;
>> + int max_combined_textures, i, unit;
>> + char str[2048];
>> +
>> + /* get limits */
>> + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&max_fs_textures);
>> + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,&max_vs_textures);
>> +
>> glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,&max_combined_textures);
>> + assert(max_fs_textures<= max_combined_textures);
>> +
>> + max_vs_textures = MIN2(max_vs_textures, max_combined_textures -
>> max_fs_textures);
>> +
>> + /* compile shaders */
>> + if (max_vs_textures) {
>> + sprintf(str, vs_source, max_vs_textures);
>> + vs = piglit_compile_shader_text(GL_VERTEX_SHADER, str);
>> + }
>> + else {
>> + vs = piglit_compile_shader_text(GL_VERTEX_SHADER,
>> vs_source_no_textures);
>> + }
>> +
>> + sprintf(str, fs_source, max_fs_textures);
>> + fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, str);
>> +
>> + prog = piglit_link_simple_program(vs, fs);
>> + glUseProgram(prog);
>> +
>> + piglit_check_gl_error(GL_NO_ERROR);
>> +
>> + /* initialize textures */
>> + unit = 0;
>> + for (i = 0; i< max_vs_textures; i++) {
>> + char name[64];
>> + sprintf(name, "vertex_tex[%i]", i);
>> + set_uniform(prog, name, unit);
>> + set_texture(unit);
>> + unit++;
>> + }
>> +
>> + for (i = 0; i< max_fs_textures; i++) {
>> + char name[64];
>> + sprintf(name, "fragment_tex[%i]", i);
>> + set_uniform(prog, name, unit);
>> + set_texture(unit);
>> + unit++;
>> + }
>> +
>> + glClearColor(0.0, 0.0, 1.0, 1.0);
>> + glGenVertexArrays(1,&vao);
>> + glBindVertexArray(vao);
>> +
>> + piglit_check_gl_error(GL_NO_ERROR);
>> +}
>
>
> Reviewed-by: Brian Paul <brianp at vmware.com>
>
> BTW, I tried to test this with NVIDIA's driver but it appears that piglit
> can't create a GL 3.1 context:
>
> $ bin/gl-3.1-max-samplers -auto
> piglit: info: Failed to create GL 3.1 core context
> piglit: info: Failed to create any GL context
> PIGLIT: {'result': 'skip' }
The issue with NVIDIA's driver is that it advertises
ARB_compatibility, so it's not a 3.1 core profile. Piglit sees that
and assumes the context creation failed and skips the test.
Marek
More information about the Piglit
mailing list