[Piglit] [PATCH] BPTC float variants test case.
Glenn Kennard
glenn.kennard at gmail.com
Sat Jul 26 08:12:36 PDT 2014
Signed-off-by: Glenn Kennard <glenn.kennard at gmail.com>
---
Mostly intended to test the hardware driver back ends rather than
the BPTC encoder.
tests/all.py | 14 +-
tests/texturing/CMakeLists.gl.txt | 1 +
tests/texturing/bptc-float.c | 363 ++++++++++++++++++++++++++++++++++++++
3 files changed, 374 insertions(+), 4 deletions(-)
create mode 100644 tests/texturing/bptc-float.c
diff --git a/tests/all.py b/tests/all.py
index a1f652c..a45049a 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -2281,10 +2281,6 @@ add_texwrap_format_tests(arb_texture_compression, 'GL_ARB_texture_compression')
arb_texture_compression['GL_TEXTURE_INTERNAL_FORMAT query'] = concurrent_test('arb_texture_compression-internal-format-query')
arb_texture_compression['unknown formats'] = concurrent_test('arb_texture_compression-invalid-formats unknown')
-arb_texture_compression_bptc = {}
-spec['ARB_texture_compression_bptc'] = arb_texture_compression_bptc
-arb_texture_compression_bptc['invalid formats'] = concurrent_test('arb_texture_compression-invalid-formats bptc')
-
ext_vertex_array_bgra = {}
spec['EXT_vertex_array_bgra'] = ext_vertex_array_bgra
add_plain_test(ext_vertex_array_bgra, 'bgra-sec-color-pointer')
@@ -2841,6 +2837,16 @@ add_fbo_generatemipmap_extension(ati_texture_compression_3dc, 'GL_ATI_texture_co
add_texwrap_format_tests(ati_texture_compression_3dc, 'GL_ATI_texture_compression_3dc')
ati_texture_compression_3dc['invalid formats'] = concurrent_test('arb_texture_compression-invalid-formats 3dc')
+arb_texture_compression_bptc = {}
+spec['ARB_texture_compression_bptc'] = arb_texture_compression_bptc
+arb_texture_compression_bptc['invalid formats'] = concurrent_test('arb_texture_compression-invalid-formats bptc')
+add_concurrent_test(arb_texture_compression_bptc, 'bptc-float signed dc')
+add_concurrent_test(arb_texture_compression_bptc, 'bptc-float signed fastest')
+add_concurrent_test(arb_texture_compression_bptc, 'bptc-float signed nicest')
+add_concurrent_test(arb_texture_compression_bptc, 'bptc-float unsigned dc')
+add_concurrent_test(arb_texture_compression_bptc, 'bptc-float unsigned fastest')
+add_concurrent_test(arb_texture_compression_bptc, 'bptc-float unsigned nicest')
+
ext_packed_float = {}
spec['EXT_packed_float'] = ext_packed_float
add_fbo_formats_tests('spec/EXT_packed_float', 'GL_EXT_packed_float')
diff --git a/tests/texturing/CMakeLists.gl.txt b/tests/texturing/CMakeLists.gl.txt
index b121163..b9c77af 100644
--- a/tests/texturing/CMakeLists.gl.txt
+++ b/tests/texturing/CMakeLists.gl.txt
@@ -13,6 +13,7 @@ link_libraries (
piglit_add_executable (1-1-linear-texture 1-1-linear-texture.c)
piglit_add_executable (array-depth-roundtrip array-depth-roundtrip.c)
piglit_add_executable (array-texture array-texture.c)
+piglit_add_executable (bptc-float bptc-float.c)
piglit_add_executable (compressedteximage compressedteximage.c)
piglit_add_executable (copytexsubimage copytexsubimage.c)
piglit_add_executable (copyteximage copyteximage.c)
diff --git a/tests/texturing/bptc-float.c b/tests/texturing/bptc-float.c
new file mode 100644
index 0000000..a08b3f4
--- /dev/null
+++ b/tests/texturing/bptc-float.c
@@ -0,0 +1,363 @@
+/** @file bptc-float.c
+ *
+ * Test that passing float data and compressing to BPTC float and unsigned float
+ * formats produce expected results both for rendering and getting float data back from
+ * texture.
+ *
+ * Also test that getting the compressed data and passing back to the driver renders bit
+ * for bit identical results to those produced by the on-line compressed texture.
+ *
+ * This is just a basic sanity check, not a compressor accuracy test.
+ */
+
+#include "piglit-util-gl.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+ config.supports_gl_compat_version = 30;
+
+ config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+#define BLOCK_SIZE 4
+#define IMAGE_WIDTH (4 * BLOCK_SIZE)
+#define IMAGE_HEIGHT (4 * BLOCK_SIZE)
+
+static GLenum compression_hint = GL_DONT_CARE;
+static bool signed_format = false;
+
+
+// 5 mantissa bits ie 32 values per exponent range, -2 bits for roundoff/dithering errors
+// -> 1/8 = 0.125.
+//static const float tolerance = 0.125f;
+static const float tolerance = 0.25f;
+
+// TODO: color code the blocks, right now its just a checkerboard
+// Each block is a solid color, to avoid compressor artifacts
+// the float values are chosen to easily be represented exactly in BPTC
+static void
+make_float_image(bool is_signed, float *out)
+{
+ int x, y;
+ for (y = 0; y < IMAGE_HEIGHT; y++) {
+ for (x = 0; x < IMAGE_WIDTH; x++) {
+ float *pixel = out + (y * IMAGE_WIDTH + x) * 3;
+ int block_x = x / BLOCK_SIZE;
+ int block_y = y / BLOCK_SIZE;
+ float v = exp((~block_x ^ block_y) & 7);
+ pixel[0] = (float)x / IMAGE_WIDTH;
+ pixel[1] = is_signed ? -v : v;
+ pixel[2] = (float)y / IMAGE_HEIGHT;
+ }
+ }
+}
+
+
+static GLuint
+make_tex(float *image_ref, bool is_signed, GLenum compression_hint)
+{
+ GLuint tex;
+
+ make_float_image(is_signed, image_ref);
+
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+
+ glHint(GL_TEXTURE_COMPRESSION_HINT, compression_hint);
+
+ glTexImage2D(GL_TEXTURE_2D, 0,
+ is_signed ? GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT : GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT,
+ IMAGE_WIDTH, IMAGE_HEIGHT, 0, GL_RGB, GL_FLOAT, image_ref),
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ return tex;
+}
+
+
+static int floatdiff(float a, float b)
+{
+ if (fabs(a - b) < tolerance) // accept larger relative errors close to zero
+ return false;
+ if (a == b)
+ return false;
+ if (b == 0)
+ return true;
+ return fabsf((b - a) / b) > tolerance;
+}
+
+
+static bool
+compare_block_results(const float *expected,
+ const float *observed)
+{
+ int y, x;
+ int rowpad = IMAGE_WIDTH * 3 - 3 * BLOCK_SIZE;
+
+ for (y = 0; y < BLOCK_SIZE; y++) {
+ for (x = 0; x < BLOCK_SIZE; x++) {
+ if (floatdiff(expected[0], observed[0]) ||
+ floatdiff(expected[1], observed[1]) ||
+ floatdiff(expected[2], observed[2])) {
+ printf("Unexpected color at %d,%d:\n"
+ "\texpected %g,%g,%g\n"
+ "\tobserved %g,%g,%g\n",
+ x, y,
+ expected[0], expected[1], expected[2],
+ observed[0], observed[1], observed[2]);
+ return false;
+ }
+
+ expected += 3;
+ observed += 3;
+ }
+
+ observed += rowpad;
+ expected += rowpad;
+ }
+
+ return true;
+}
+
+
+static bool
+compare_precompressed(GLuint online_tex, const float *online_ref, bool is_signed)
+{
+ uint8_t compressed_data[(IMAGE_WIDTH/BLOCK_SIZE) * (IMAGE_HEIGHT/BLOCK_SIZE) * 16] = {0};
+ float precompressed_image[IMAGE_WIDTH * IMAGE_HEIGHT * 3] = {0};
+ bool pass = true;
+ GLuint tex;
+ int n;
+
+ glBindTexture(GL_TEXTURE_2D, online_tex);
+
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &n);
+ if (n != sizeof(compressed_data)) {
+ printf("GL_TEXTURE_COMPRESSED_IMAGE_SIZE returning incorrect size %d, expected %zd\n",
+ n, sizeof(compressed_data));
+ return false;
+ }
+ glGetCompressedTexImage(GL_TEXTURE_2D, 0, compressed_data);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // Pre-compressed data should bit bit identical rendering results
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0,
+ is_signed ? GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT : GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT,
+ IMAGE_WIDTH, IMAGE_HEIGHT, 0, sizeof(compressed_data), compressed_data),
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ // draw pre-compressed texture
+ glEnable(GL_TEXTURE_2D);
+ piglit_draw_rect_tex(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT,
+ 0.0f, 0.0f, 1.0f, 1.0f);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &tex);
+
+ glReadPixels(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT,
+ GL_RGB, GL_FLOAT, precompressed_image);
+
+ if (memcmp(online_ref, precompressed_image, sizeof(precompressed_image))) {
+ pass = false;
+ }
+
+ printf("render of online compressed texture and precompressed texture produces identical results: %s\n",
+ pass ? "pass" : "fail");
+
+ return pass;
+}
+
+
+static bool
+render_texture(bool is_signed,
+ GLenum compress_hint,
+ float *image_ref,
+ float *render_data,
+ float *get_data)
+{
+ GLuint tex;
+ bool pass;
+
+ tex = make_tex(image_ref, is_signed, compress_hint);
+
+ memset(render_data, 0xff, IMAGE_WIDTH * IMAGE_HEIGHT * 3);
+ memset(get_data, 0xff, IMAGE_WIDTH * IMAGE_HEIGHT * 3);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glEnable(GL_TEXTURE_2D);
+
+ piglit_draw_rect_tex(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT,
+ 0.0f, 0.0f, 1.0f, 1.0f);
+
+ glDisable(GL_TEXTURE_2D);
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
+ glReadPixels(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT,
+ GL_RGB, GL_FLOAT, render_data);
+
+ glGetTexImage(GL_TEXTURE_2D,
+ 0, /* level */
+ GL_RGB,
+ GL_FLOAT,
+ get_data);
+
+ pass = compare_precompressed(tex, render_data, is_signed);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &tex);
+
+ return pass;
+}
+
+
+static GLuint
+make_float_fbo(GLuint *fbo, GLuint *fbotex)
+{
+ GLenum e;
+ GLuint prev_fbo;
+
+ glGenTextures(1, fbotex);
+ glBindTexture(GL_TEXTURE_2D, *fbotex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, IMAGE_WIDTH, IMAGE_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint *)&prev_fbo);
+ glGenFramebuffers(1, fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *fbotex, 0);
+
+ e = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (e != GL_FRAMEBUFFER_COMPLETE) {
+ fprintf(stderr, "FBO incomplete: error 0x%x\n", e);
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ glClearColor(1,0,0,1);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ return prev_fbo;
+}
+
+
+static void
+draw_float_fbo(GLuint drawfbo, GLuint fbotex)
+{
+ glBindFramebuffer(GL_FRAMEBUFFER, drawfbo);
+ glBindTexture(GL_TEXTURE_2D, fbotex);
+ glEnable(GL_TEXTURE_2D);
+
+ piglit_draw_rect_tex(0, 0, IMAGE_WIDTH * 4, IMAGE_HEIGHT * 4,
+ 0.0f, 0.0f, 1.0f, 1.0f);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+}
+
+
+static bool
+check_block(const float *image_ref,
+ const float *render_data,
+ const float *get_data)
+{
+ bool overall_result = true;
+ bool pass;
+
+ pass = compare_block_results(image_ref,
+ render_data);
+ printf("\trender block: %s\n", pass ? "pass" : "fail");
+
+ overall_result &= pass;
+
+ pass = compare_block_results(image_ref,
+ get_data);
+ printf("\tglGetTexImage: %s\n", pass ? "pass" : "fail");
+
+ overall_result &= pass;
+
+ return overall_result;
+}
+
+
+enum piglit_result
+piglit_display(void)
+{
+ bool pass;
+ float image_ref[IMAGE_WIDTH * IMAGE_HEIGHT * 3];
+ float render_data[IMAGE_WIDTH * IMAGE_HEIGHT * 3];
+ float get_data[IMAGE_WIDTH * IMAGE_HEIGHT * 3];
+ int offset;
+ int x, y;
+ GLuint fbotex, fbo, prev_fbo;
+
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ prev_fbo = make_float_fbo(&fbo, &fbotex);
+ pass = render_texture(signed_format, compression_hint, image_ref, render_data, get_data);
+ draw_float_fbo(prev_fbo, fbotex);
+
+ glDeleteFramebuffers(1, &fbo);
+ glDeleteTextures(1, &fbotex);
+
+ for (y = 0; y < IMAGE_HEIGHT; y += BLOCK_SIZE) {
+ for (x = 0; x < IMAGE_WIDTH; x += BLOCK_SIZE) {
+ offset = (y * IMAGE_WIDTH + x) * 3;
+ printf ("Checking block %d,%d:\n", x / BLOCK_SIZE, y / BLOCK_SIZE);
+ pass &= check_block(image_ref + offset,
+ render_data + offset,
+ get_data + offset);
+ }
+ puts("");
+ }
+
+ piglit_present_results();
+
+ return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+
+void
+piglit_init(int argc, char **argv)
+{
+ int i;
+ for (i = 1; i < argc; i++) {
+ char *opt = argv[i];
+ if (!strcmp(opt, "dc")) compression_hint = GL_DONT_CARE;
+ else if (!strcmp(opt, "fastest")) compression_hint = GL_FASTEST;
+ else if (!strcmp(opt, "nicest")) compression_hint = GL_NICEST;
+ else if (!strcmp(opt, "unsigned")) signed_format = false;
+ else if (!strcmp(opt, "signed")) signed_format = true;
+ }
+
+
+ if (piglit_get_gl_version() < 42 &&
+ !piglit_is_extension_supported("GL_ARB_texture_compression_bptc")) {
+ printf("OpenGL 4.2 or GL_ARB_texture_compression_bptc "
+ "is required.\n");
+ piglit_report_result(PIGLIT_SKIP);
+ }
+
+ if (piglit_get_gl_version() < 30 &&
+ !piglit_is_extension_supported("GL_ARB_color_buffer_float")) {
+ printf("OpenGL 3.0 or GL_ARB_color_buffer_float is required\n");
+ piglit_report_result(PIGLIT_SKIP);
+ }
+
+ piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
+}
--
1.8.3.2
More information about the Piglit
mailing list