Allows verification of texelFetch with all six flavors of MS sampler. - Put lod/sample_index in the fourth channel of the texture, so we can verify that the correct lod/sample was sampled. - For multisample targets, render the test pattern rather than uploading it. GL won't let us do a direct upload into these texture targets, and the alternative (upload to a staging texture; copy to target) is even messier. - Accept sample count as an extra parameter after sampler - Add existing swizzle option to usage string - Use smaller formats for multisample tests, to avoid running into some hardware limits.
This replaces the earlier arb_texture_multisample-texel-fetch-execution and arb_texture_multisample-texel-fetch-execution-array tests, and is much more thorough (it showed Gen7 was still messed up :( !) V3: - Increase window height so we can test 8x. - Don't break the format-based extension checks. Signed-off-by: Chris Forbes <chr...@ijw.co.nz> --- tests/all.tests | 6 + tests/texturing/shaders/common.c | 34 ++++-- tests/texturing/shaders/common.h | 2 + tests/texturing/shaders/texelFetch.c | 226 +++++++++++++++++++++++++++++++---- 4 files changed, 238 insertions(+), 30 deletions(-) diff --git a/tests/all.tests b/tests/all.tests index 5ab0a2d..a041515 100644 --- a/tests/all.tests +++ b/tests/all.tests @@ -867,6 +867,12 @@ for sample_count in MSAA_SAMPLE_COUNTS: # fb-completeness spec['ARB_texture_multisample/fb-completeness/%d' % (sample_count,)] = \ concurrent_test('arb_texture_multisample-fb-completeness %d' % (sample_count,)) + # texel-fetch execution + for stage in ['vs','fs']: + for sampler in samplers_atm: + spec['ARB_texture_multisample/texelFetch/%d-%s-%s' % ( + sample_count, stage, sampler)] = \ + concurrent_test('texelFetch %s %s %d' % (stage, sampler, sample_count)) add_concurrent_test(arb_texture_multisample, 'arb_texture_multisample-texstate') add_concurrent_test(arb_texture_multisample, 'arb_texture_multisample-sample-mask') add_concurrent_test(arb_texture_multisample, 'arb_texture_multisample-sample-mask-value') diff --git a/tests/texturing/shaders/common.c b/tests/texturing/shaders/common.c index 120e424..0b13d47 100644 --- a/tests/texturing/shaders/common.c +++ b/tests/texturing/shaders/common.c @@ -151,10 +151,11 @@ compute_miplevel_info() miplevels = (int) log2f(max_dimension) + 1; if (sampler.target == GL_TEXTURE_RECTANGLE || - sampler.target == GL_TEXTURE_BUFFER || - sampler.target == GL_TEXTURE_2D_MULTISAMPLE || - sampler.target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) + sampler.target == GL_TEXTURE_BUFFER) miplevels = 1; + if (sampler.target == GL_TEXTURE_2D_MULTISAMPLE || + sampler.target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) + miplevels = sample_count; /* Compute the size of each miplevel */ level_size = malloc(miplevels * sizeof(int *)); @@ -165,7 +166,11 @@ compute_miplevel_info() level_size[l] = malloc(3 * sizeof(int)); for (i = 0; i < 3 - is_array; i++) - level_size[l][i] = max2(level_size[l-1][i] / 2, 1); + if (has_samples()) + /* same size for all sample planes */ + level_size[l][i] = level_size[l-1][i]; + else + level_size[l][i] = max2(level_size[l-1][i] / 2, 1); if (is_array) level_size[l][2] = base_size[2]; @@ -190,6 +195,13 @@ has_slices() } bool +has_samples() +{ + return sampler.target == GL_TEXTURE_2D_MULTISAMPLE || + sampler.target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY; +} + +bool is_array_sampler() { return sampler.target == GL_TEXTURE_1D_ARRAY || @@ -279,15 +291,20 @@ select_sampler(const char *name) sampler.type = samplers[i].type; sampler.target = samplers[i].target; + /* Use 32bpc sized formats where possible; drop down to 16bpc for + * testing multisample targets to avoid hitting some hardware limits. + * on i965. + */ + if (name[0] == 'i') { sampler.data_type = GL_INT; sampler.format = GL_RGBA_INTEGER; - sampler.internal_format = GL_RGBA32I; + sampler.internal_format = has_samples() ? GL_RGBA16I : GL_RGBA32I; sampler.return_type = "ivec4"; } else if (name[0] == 'u') { sampler.data_type = GL_UNSIGNED_INT; sampler.format = GL_RGBA_INTEGER; - sampler.internal_format = GL_RGBA32UI; + sampler.internal_format = has_samples() ? GL_RGBA16UI : GL_RGBA32UI; sampler.return_type = "uvec4"; } else if (strstr(name, "Shadow")) { /* Shadow Sampler */ @@ -298,7 +315,7 @@ select_sampler(const char *name) } else { sampler.data_type = GL_FLOAT; sampler.format = GL_RGBA; - sampler.internal_format = GL_RGBA32F; + sampler.internal_format = has_samples() ? GL_RGBA16F : GL_RGBA32F; sampler.return_type = "vec4"; } @@ -321,12 +338,15 @@ require_GL_features(enum shader_target test_stage) switch (sampler.internal_format) { case GL_RGBA32I: + case GL_RGBA16I: piglit_require_extension("GL_EXT_texture_integer"); break; case GL_RGBA32UI: + case GL_RGBA16UI: piglit_require_gl_version(30); break; case GL_RGBA32F: + case GL_RGBA16F: piglit_require_extension("GL_ARB_texture_float"); break; } diff --git a/tests/texturing/shaders/common.h b/tests/texturing/shaders/common.h index a4e8cd7..878faec 100644 --- a/tests/texturing/shaders/common.h +++ b/tests/texturing/shaders/common.h @@ -81,6 +81,7 @@ struct sampler_info /** Whether or not we're using GL_EXT_texture_swizzle */ bool swizzling; +int sample_count; extern int shader_version; /** @@ -97,6 +98,7 @@ float max2(float x, float y); bool has_height(); bool has_slices(); +bool has_samples(); bool is_array_sampler(); bool is_shadow_sampler(); diff --git a/tests/texturing/shaders/texelFetch.c b/tests/texturing/shaders/texelFetch.c index 50e91a6..ebfdfe0 100644 --- a/tests/texturing/shaders/texelFetch.c +++ b/tests/texturing/shaders/texelFetch.c @@ -84,11 +84,13 @@ PIGLIT_GL_TEST_CONFIG_BEGIN config.supports_gl_core_version = 31; config.window_width = 355; - config.window_height = 250; + config.window_height = 350; config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE; PIGLIT_GL_TEST_CONFIG_END +#define MAX_LOD_OR_SAMPLES 8.0 + /** Vertex shader attribute locations */ const int pos_loc = 0; const int texcoord_loc = 1; @@ -121,7 +123,7 @@ compute_divisors(int lod, float *divisors) divisors[0] = max2(level_size[lod][0] - 1, 1); divisors[1] = max2(level_size[lod][1] - 1, 1); divisors[2] = max2(level_size[lod][2] - 1, 1); - divisors[3] = 1.0; + divisors[3] = MAX_LOD_OR_SAMPLES; if (sampler.data_type != GL_UNSIGNED_INT) divisors[0] = -divisors[0]; @@ -133,6 +135,8 @@ piglit_display() int i, l, z; bool pass = true; + glViewport(0, 0, piglit_width, piglit_height); + glClearColor(0.1, 0.1, 0.1, 1.0); glClear(GL_COLOR_BUFFER_BIT); @@ -261,6 +265,150 @@ generate_VBOs() glEnableVertexAttribArray(texcoord_loc); } +/* like piglit_draw_rect(), but works in a core context too. + * pretty silly and wasteful (binds a throwaway VAO and BO) */ +static void +draw_rect_core(int x, int y, int w, int h) +{ + float verts[4][4]; + GLuint bo, vao; + + 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; + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glGenBuffers(1, &bo); + glBindBuffer(GL_ARRAY_BUFFER, bo); + glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(float), + verts, GL_STATIC_DRAW); + glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0); + glEnableVertexAttribArray(0); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glBindVertexArray(0); + glDeleteBuffers(1, &bo); + glDeleteVertexArrays(1, &vao); +} + +/** + * Generate the same test pattern as generate_texture() does, but do it in the shader. + * This is a silly workaround for not being able to just upload directly. + */ +static void +upload_multisample_data(GLuint tex, int width, int height, + int layers, int samples) +{ + GLuint oldFBO, FBO; + int si; + char *fs_code; + int vs, fs; + int staging_program = 0; + int layer_loc = 0; + int si_loc = 0; + + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint *) &oldFBO); + if (is_array_sampler()) + glTexImage3DMultisample(sampler.target, + samples, sampler.internal_format, + width, height, layers, GL_TRUE); + else + glTexImage2DMultisample(sampler.target, + samples, sampler.internal_format, + width, height, GL_TRUE); + if (!piglit_check_gl_error(GL_NO_ERROR)) { + printf("Error creating multisample texture\n"); + piglit_report_result(PIGLIT_FAIL); + } + + vs = piglit_compile_shader_text(GL_VERTEX_SHADER, + "#version 130\n" + "#extension GL_ARB_explicit_attrib_location: require\n" + "layout(location=0) in vec4 pos;\n" + "void main() {\n" + " gl_Position = pos;\n" + "}\n"); + asprintf(&fs_code, + "#version 130\n" + "#extension GL_ARB_explicit_attrib_location: require\n" + "#extension GL_ARB_fragment_coord_conventions: require\n" + "uniform int layer;\n" + "uniform int si;\n" + "layout(pixel_center_integer) in vec4 gl_FragCoord;\n" + "layout(location=0) out %s o;\n" + "void main() {\n" + " o = %s(%sgl_FragCoord.x, gl_FragCoord.y, layer, si);\n" + "}\n", + sampler.return_type, + sampler.return_type, + sampler.data_type == GL_UNSIGNED_INT ? "" : "-"); + fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_code); + if (!fs) { + printf("Failed to compile staging program.\n"); + piglit_report_result(PIGLIT_FAIL); + } + staging_program = piglit_link_simple_program(vs,fs); + if (!piglit_link_check_status(staging_program)) + piglit_report_result(PIGLIT_FAIL); + + layer_loc = glGetUniformLocation(staging_program, "layer"); + si_loc = glGetUniformLocation(staging_program, "si"); + + glUseProgram(staging_program); + if (!piglit_check_gl_error(GL_NO_ERROR)) { + printf("glUseProgram failed\n"); + piglit_report_result(PIGLIT_FAIL); + } + + glGenFramebuffers(1, &FBO); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO); + glViewport(0, 0, width, height); + + glEnable(GL_SAMPLE_MASK); + + for (si=0; si < samples; si++) { + glUniform1i(si_loc, si); + glSampleMaski(0, 1<<si); + + if (is_array_sampler()) { + int layer; + for(layer = 0; layer < layers; layer++) { + glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + tex, 0, layer); + glUniform1i(layer_loc, layer); + draw_rect_core(-1, -1, 2, 2); + } + } + else { + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + sampler.target, tex, 0); + + glUniform1i(layer_loc, 0); + draw_rect_core(-1, -1, 2, 2); + } + } + + glDisable(GL_SAMPLE_MASK); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldFBO); +} + /** * Create texel data. */ @@ -281,18 +429,21 @@ generate_texture() glGenTextures(1, &tex); glBindTexture(target, tex); - if (sampler.target == GL_TEXTURE_RECTANGLE) { - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } else { - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + if (!has_samples()) { + if (sampler.target == GL_TEXTURE_RECTANGLE) { + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } else { + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (swizzling) + glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, + (GLint *) sampler.swizzle); } - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (swizzling) - glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, - (GLint *) sampler.swizzle); expected_colors = calloc(miplevels, sizeof(float **)); @@ -321,24 +472,24 @@ generate_texture() f_ptr[0] = nx; f_ptr[1] = y; f_ptr[2] = z; - f_ptr[3] = 1.0; + f_ptr[3] = l; i_ptr[0] = nx; i_ptr[1] = y; i_ptr[2] = z; - i_ptr[3] = 1; + i_ptr[3] = l; u_ptr[0] = nx; u_ptr[1] = y; u_ptr[2] = z; - u_ptr[3] = 1; + u_ptr[3] = l; compute_divisors(l, divisors); expected_ptr[0] = f_ptr[0]/divisors[0]; expected_ptr[1] = f_ptr[1]/divisors[1]; expected_ptr[2] = f_ptr[2]/divisors[2]; - expected_ptr[3] = 1.0; + expected_ptr[3] = f_ptr[3]/divisors[3]; swizzle(expected_ptr); f_ptr += 4; @@ -365,8 +516,14 @@ generate_texture() break; } - upload_miplevel_data(target, l, level_image); + if (!has_samples()) + upload_miplevel_data(target, l, level_image); } + + if (has_samples()) + upload_multisample_data(tex, level_size[0][0], + level_size[0][1], level_size[0][2], + sample_count); } /** @@ -381,9 +538,11 @@ coordinate_size() case GL_TEXTURE_2D: case GL_TEXTURE_1D_ARRAY: case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_MULTISAMPLE: return 2; case GL_TEXTURE_3D: case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: return 3; default: assert(!"Should not get here."); @@ -432,6 +591,7 @@ generate_GLSL(enum shader_target test_stage) case VS: asprintf(&vs_code, "#version %d\n" + "%s\n" "#define ivec1 int\n" "flat out %s color;\n" "in vec4 pos;\n" @@ -443,6 +603,7 @@ generate_GLSL(enum shader_target test_stage) " gl_Position = pos;\n" "}\n", shader_version, + has_samples() ? "#extension GL_ARB_texture_multisample: require" : "", sampler.return_type, sampler.name, offset_func, coordinate_size(), @@ -475,6 +636,7 @@ generate_GLSL(enum shader_target test_stage) shader_version); asprintf(&fs_code, "#version %d\n" + "%s\n" "#define ivec1 int\n" "flat in ivec4 tc;\n" "uniform vec4 divisor;\n" @@ -485,6 +647,7 @@ generate_GLSL(enum shader_target test_stage) " gl_FragColor = color/divisor;\n" "}\n", shader_version, + has_samples() ? "#extension GL_ARB_texture_multisample: require" : "", sampler.name, offset_func, coordinate_size(), @@ -545,6 +708,8 @@ supported_sampler() case GL_TEXTURE_1D_ARRAY: case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: return true; } return false; @@ -554,7 +719,7 @@ void fail_and_show_usage() { printf("Usage: texelFetch [140] [offset] <vs|fs> <sampler type> " - "[piglit args...]\n"); + "[sample_count] [swizzle] [piglit args...]\n"); piglit_report_result(PIGLIT_FAIL); } @@ -593,6 +758,21 @@ piglit_init(int argc, char **argv) if (!sampler_found && (sampler_found = select_sampler(argv[i]))) continue; + /* Maybe it's the sample count? */ + if (sampler_found && has_samples() && !sample_count) { + if ((sample_count = atoi(argv[i]))) { + /* check it */ + GLint max_samples; + glGetIntegerv(GL_MAX_SAMPLES, &max_samples); + if (sample_count > max_samples) { + printf("Sample count of %d not supported, >MAX_SAMPLES\n", + sample_count); + piglit_report_result(PIGLIT_SKIP); + } + } + continue; + } + if (!swizzling && (swizzling = parse_swizzle(argv[i]))) continue; @@ -614,14 +794,14 @@ piglit_init(int argc, char **argv) tex_location = glGetUniformLocation(prog, "tex"); divisor_loc = glGetUniformLocation(prog, "divisor"); - glUseProgram(prog); - - glUniform1i(tex_location, 0); - /* Create textures and set miplevel info */ set_base_size(); compute_miplevel_info(); generate_texture(); generate_VBOs(); + + glUseProgram(prog); + + glUniform1i(tex_location, 0); } -- 1.8.1.4 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/piglit