From e6ebebc4853c98aa387b2c39a886a0c1173e93fb Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 7 Aug 2009 01:20:01 +0100 Subject: llvmpipe: Factor out shared test code into a separate module. --- src/gallium/drivers/llvmpipe/SConscript | 2 +- src/gallium/drivers/llvmpipe/lp_bld_type.h | 2 + src/gallium/drivers/llvmpipe/lp_test.h | 124 ++++++++ src/gallium/drivers/llvmpipe/lp_test_blend.c | 250 +++++------------ src/gallium/drivers/llvmpipe/lp_test_main.c | 404 +++++++++++++++++++++++++++ 5 files changed, 598 insertions(+), 184 deletions(-) create mode 100644 src/gallium/drivers/llvmpipe/lp_test.h create mode 100644 src/gallium/drivers/llvmpipe/lp_test_main.c (limited to 'src') diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript index 58e6a888e8..7982e4219a 100644 --- a/src/gallium/drivers/llvmpipe/SConscript +++ b/src/gallium/drivers/llvmpipe/SConscript @@ -64,7 +64,7 @@ env.Program( env.Program( target = 'lp_test_blend', - source = ['lp_test_blend.c'], + source = ['lp_test_blend.c', 'lp_test_main.c'], ) Export('llvmpipe') diff --git a/src/gallium/drivers/llvmpipe/lp_bld_type.h b/src/gallium/drivers/llvmpipe/lp_bld_type.h index 566a86ed06..37d6885049 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_type.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_type.h @@ -48,6 +48,8 @@ */ #define LP_MAX_VECTOR_LENGTH 16 +#define LP_MAX_TYPE_WIDTH 64 + /** * The LLVM type system can't conveniently express all the things we care about diff --git a/src/gallium/drivers/llvmpipe/lp_test.h b/src/gallium/drivers/llvmpipe/lp_test.h new file mode 100644 index 0000000000..dd173fe4c5 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_test.h @@ -0,0 +1,124 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * Shared testing code. + * + * @author Jose Fonseca + */ + + +#ifndef LP_TEST_H +#define LP_TEST_H + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "pipe/p_state.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_debug_dump.h" + +#include "lp_bld_type.h" + + +void +write_tsv_header(FILE *fp); + + +boolean +test_some(unsigned verbose, FILE *fp, unsigned long n); + + +boolean +test_all(unsigned verbose, FILE *fp); + + +static INLINE uint64_t +rdtsc(void) +{ +#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) + uint32_t hi, lo; + __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); + return ((uint64_t)lo) | (((uint64_t)hi) << 32); +#else + return 0; +#endif +} + + +float +random_float(void); + + +void +dump_type(FILE *fp, union lp_type type); + + +double +read_elem(union lp_type type, const void *src, unsigned index); + + +void +write_elem(union lp_type type, void *dst, unsigned index, double src); + + +void +random_elem(union lp_type type, void *dst, unsigned index); + + +void +read_vec(union lp_type type, const void *src, double *dst); + + +void +write_vec(union lp_type type, void *dst, const double *src); + + +void +random_vec(union lp_type type, void *dst); + + +boolean +compare_vec(union lp_type type, const void *res, const double *ref); + + +void +dump_vec(FILE *fp, union lp_type type, const void *src); + + +#endif /* !LP_TEST_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_test_blend.c b/src/gallium/drivers/llvmpipe/lp_test_blend.c index 56cd800b37..f42a9a9e42 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_blend.c +++ b/src/gallium/drivers/llvmpipe/lp_test_blend.c @@ -37,34 +37,16 @@ */ -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "pipe/p_state.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_debug_dump.h" - #include "lp_bld.h" #include "lp_bld_type.h" #include "lp_bld_arit.h" - - -unsigned verbose = 0; +#include "lp_test.h" typedef void (*blend_test_ptr_t)(const void *src, const void *dst, const void *con, void *res); -static void +void write_tsv_header(FILE *fp) { fprintf(fp, @@ -145,19 +127,6 @@ dump_blend_type(FILE *fp, } -static INLINE uint64_t -rdtsc(void) -{ -#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) - uint32_t hi, lo; - __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); - return ((uint64_t)lo) | (((uint64_t)hi) << 32); -#else - return 0; -#endif -} - - static LLVMValueRef add_blend_test(LLVMModuleRef module, const struct pipe_blend_state *blend, @@ -210,13 +179,6 @@ add_blend_test(LLVMModuleRef module, } -static float -random_float(void) -{ - return (float)((double)random()/(double)RAND_MAX); -} - - /** Add and limit result to ceiling of 1.0 */ #define ADD_SAT(R, A, B) \ do { \ @@ -233,13 +195,13 @@ do { \ static void compute_blend_ref_term(unsigned rgb_factor, unsigned alpha_factor, - const float *factor, - const float *src, - const float *dst, - const float *con, - float *term) + const double *factor, + const double *src, + const double *dst, + const double *con, + double *term) { - float temp; + double temp; switch (rgb_factor) { case PIPE_BLENDFACTOR_ONE: @@ -379,13 +341,13 @@ compute_blend_ref_term(unsigned rgb_factor, static void compute_blend_ref(const struct pipe_blend_state *blend, - const float *src, - const float *dst, - const float *con, - float *res) + const double *src, + const double *dst, + const double *con, + double *res) { - float src_term[4]; - float dst_term[4]; + double src_term[4]; + double dst_term[4]; compute_blend_ref_term(blend->rgb_src_factor, blend->alpha_src_factor, src, src, dst, con, src_term); compute_blend_ref_term(blend->rgb_dst_factor, blend->alpha_dst_factor, dst, src, dst, con, dst_term); @@ -449,7 +411,8 @@ compute_blend_ref(const struct pipe_blend_state *blend, static boolean -test_one(FILE *fp, +test_one(unsigned verbose, + FILE *fp, const struct pipe_blend_state *blend, union lp_type type) { @@ -464,7 +427,7 @@ test_one(FILE *fp, const unsigned n = 32; int64_t cycles[n]; double cycles_avg = 0.0; - unsigned i, j, k; + unsigned i, j; if(verbose >= 1) dump_blend_type(stdout, blend, type); @@ -510,108 +473,64 @@ test_one(FILE *fp, success = TRUE; for(i = 0; i < n && success; ++i) { + uint8_t src[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8]; + uint8_t dst[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8]; + uint8_t con[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8]; + uint8_t res[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8]; + double ref[LP_MAX_VECTOR_LENGTH]; int64_t start_counter = 0; int64_t end_counter = 0; - if(type.floating && type.width == 32) { - float src[LP_MAX_VECTOR_LENGTH]; - float dst[LP_MAX_VECTOR_LENGTH]; - float con[LP_MAX_VECTOR_LENGTH]; - float ref[LP_MAX_VECTOR_LENGTH]; - float res[LP_MAX_VECTOR_LENGTH]; - - for(j = 0; j < type.length; ++j) { - src[j] = random_float(); - dst[j] = random_float(); - con[j] = random_float(); - } + random_vec(type, src); + random_vec(type, dst); + random_vec(type, con); + + { + double fsrc[LP_MAX_VECTOR_LENGTH]; + double fdst[LP_MAX_VECTOR_LENGTH]; + double fcon[LP_MAX_VECTOR_LENGTH]; + + read_vec(type, src, fsrc); + read_vec(type, dst, fdst); + read_vec(type, con, fcon); for(j = 0; j < type.length; j += 4) - compute_blend_ref(blend, src + j, dst + j, con + j, ref + j); - - start_counter = rdtsc(); - blend_test_ptr(src, dst, con, res); - end_counter = rdtsc(); - - for(j = 0; j < type.length; ++j) - if(fabs(res[j] - ref[j]) > FLT_EPSILON) - success = FALSE; - - if (!success) { - dump_blend_type(stderr, blend, type); - fprintf(stderr, "\n"); - fprintf(stderr, "MISMATCH\n"); - fprintf(stderr, " Result: "); - for(j = 0; j < type.length; ++j) - fprintf(stderr, " %f", res[j]); - fprintf(stderr, "\n"); - fprintf(stderr, " Expected: "); - for(j = 0; j < type.length; ++j) - fprintf(stderr, " %f", ref[j]); - fprintf(stderr, "\n"); - } + compute_blend_ref(blend, fsrc + j, fdst + j, fcon + j, ref + j); } - else if(!type.floating && !type.fixed && !type.sign && type.norm && type.width == 8) { - uint8_t src[LP_MAX_VECTOR_LENGTH]; - uint8_t dst[LP_MAX_VECTOR_LENGTH]; - uint8_t con[LP_MAX_VECTOR_LENGTH]; - uint8_t ref[LP_MAX_VECTOR_LENGTH]; - uint8_t res[LP_MAX_VECTOR_LENGTH]; - - for(j = 0; j < type.length; ++j) { - src[j] = random() & 0xff; - dst[j] = random() & 0xff; - con[j] = random() & 0xff; - } - for(j = 0; j < type.length; j += 4) { - float srcf[4]; - float dstf[4]; - float conf[4]; - float reff[4]; + start_counter = rdtsc(); + blend_test_ptr(src, dst, con, res); + end_counter = rdtsc(); - for(k = 0; k < 4; ++k) { - srcf[k] = (1.0f/255.0f)*src[j + k]; - dstf[k] = (1.0f/255.0f)*dst[j + k]; - conf[k] = (1.0f/255.0f)*con[j + k]; - } + cycles[i] = end_counter - start_counter; - compute_blend_ref(blend, srcf, dstf, conf, reff); + success = compare_vec(type, res, ref); - for(k = 0; k < 4; ++k) - ref[j + k] = (uint8_t)(reff[k]*255.0f + 0.5f); - } + if (!success) { + dump_blend_type(stderr, blend, type); + fprintf(stderr, "\n"); + fprintf(stderr, "MISMATCH\n"); - start_counter = rdtsc(); - blend_test_ptr(src, dst, con, res); - end_counter = rdtsc(); + fprintf(stderr, " Src: "); + dump_vec(stderr, type, src); + fprintf(stderr, "\n"); - for(j = 0; j < type.length; ++j) { - int delta = (int)res[j] - (int)ref[j]; - if (delta < 0) - delta = -delta; - if(delta > 1) - success = FALSE; - } + fprintf(stderr, " Dst: "); + dump_vec(stderr, type, dst); + fprintf(stderr, "\n"); - if (!success) { - dump_blend_type(stderr, blend, type); - fprintf(stderr, "\n"); - fprintf(stderr, "MISMATCH\n"); - fprintf(stderr, " Result: "); - for(j = 0; j < type.length; ++j) - fprintf(stderr, " %3u", res[j]); - fprintf(stderr, "\n"); - fprintf(stderr, " Expected: "); - for(j = 0; j < type.length; ++j) - fprintf(stderr, " %3u", ref[j]); - fprintf(stderr, "\n"); - } - } - else - assert(0); + fprintf(stderr, " Con: "); + dump_vec(stderr, type, con); + fprintf(stderr, "\n"); - cycles[i] = end_counter - start_counter; + fprintf(stderr, " Res: "); + dump_vec(stderr, type, res); + fprintf(stderr, "\n"); + + fprintf(stderr, " Ref: "); + dump_vec(stderr, type, ref); + fprintf(stderr, "\n"); + } } /* @@ -725,8 +644,8 @@ const unsigned num_factors = sizeof(blend_factors)/sizeof(blend_factors[0]); const unsigned num_types = sizeof(blend_types)/sizeof(blend_types[0]); -static boolean -test_all(FILE *fp) +boolean +test_all(unsigned verbose, FILE *fp) { const unsigned *rgb_func; const unsigned *rgb_src_factor; @@ -759,7 +678,7 @@ test_all(FILE *fp) blend.alpha_src_factor = *alpha_src_factor; blend.alpha_dst_factor = *alpha_dst_factor; - if(!test_one(fp, &blend, *type)) + if(!test_one(verbose, fp, &blend, *type)) success = FALSE; } @@ -774,8 +693,8 @@ test_all(FILE *fp) } -static boolean -test_some(FILE *fp, unsigned long n) +boolean +test_some(unsigned verbose, FILE *fp, unsigned long n) { const unsigned *rgb_func; const unsigned *rgb_src_factor; @@ -813,45 +732,10 @@ test_some(FILE *fp, unsigned long n) blend.alpha_src_factor = *alpha_src_factor; blend.alpha_dst_factor = *alpha_dst_factor; - if(!test_one(fp, &blend, *type)) + if(!test_one(verbose, fp, &blend, *type)) success = FALSE; } } return success; } - - -int main(int argc, char **argv) -{ - unsigned long n = 1000; - FILE *fp = NULL; - unsigned i; - boolean success; - - for(i = 1; i < argc; ++i) { - if(strcmp(argv[i], "-v") == 0) - ++verbose; - else if(strcmp(argv[i], "-o") == 0) - fp = fopen(argv[++i], "wt"); - else - n = atoi(argv[i]); - } - - if(fp) { - /* Warm up the caches */ - test_some(NULL, 100); - - write_tsv_header(fp); - } - - if(n) - success = test_some(fp, n); - else - success = test_all(fp); - - if(fp) - fclose(fp); - - return success ? 0 : 1; -} diff --git a/src/gallium/drivers/llvmpipe/lp_test_main.c b/src/gallium/drivers/llvmpipe/lp_test_main.c new file mode 100644 index 0000000000..2ce3fa1c0b --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_test_main.c @@ -0,0 +1,404 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +/** + * @file + * Shared testing code. + * + * @author Jose Fonseca + */ + + +#include "lp_bld_const.h" +#include "lp_test.h" + + +void +dump_type(FILE *fp, + union lp_type type) +{ + fprintf(fp, "%s%u%sx%u", + type.floating ? "f" : (type.fixed ? "h" : (type.sign ? "s" : "u")), + type.width, + type.norm ? "n" : "", + type.length); +} + + +double +read_elem(union lp_type type, const void *src, unsigned index) +{ + double scale = lp_const_scale(type); + double value; + assert(index < type.length); + if (type.floating) { + switch(type.width) { + case 32: + value = *((const float *)src + index); + break; + case 64: + value = *((const double *)src + index); + break; + default: + assert(0); + return 0.0; + } + } + else { + if(type.sign) { + switch(type.width) { + case 8: + value = *((const int8_t *)src + index); + break; + case 16: + value = *((const int16_t *)src + index); + break; + case 32: + value = *((const int32_t *)src + index); + break; + case 64: + value = *((const int64_t *)src + index); + break; + default: + assert(0); + return 0.0; + } + } + else { + switch(type.width) { + case 8: + value = *((const uint8_t *)src + index); + break; + case 16: + value = *((const uint16_t *)src + index); + break; + case 32: + value = *((const uint32_t *)src + index); + break; + case 64: + value = *((const uint64_t *)src + index); + break; + default: + assert(0); + return 0.0; + } + } + } + return value/scale; +} + + +void +write_elem(union lp_type type, void *dst, unsigned index, double src) +{ + double scale = lp_const_scale(type); + double value = scale*src; + assert(index < type.length); + if (type.floating) { + switch(type.width) { + case 32: + *((float *)dst + index) = (float)(value); + break; + case 64: + *((double *)dst + index) = value; + break; + default: + assert(0); + } + } + else { + if(type.sign) { + switch(type.width) { + case 8: + *((int8_t *)dst + index) = (int8_t)round(value); + break; + case 16: + *((int16_t *)dst + index) = (int16_t)round(value); + break; + case 32: + *((int32_t *)dst + index) = (int32_t)round(value); + break; + case 64: + *((int64_t *)dst + index) = (int32_t)round(value); + break; + default: + assert(0); + } + } + else { + switch(type.width) { + case 8: + *((uint8_t *)dst + index) = (uint8_t)round(value); + break; + case 16: + *((uint16_t *)dst + index) = (uint16_t)round(value); + break; + case 32: + *((uint32_t *)dst + index) = (uint32_t)round(value); + break; + case 64: + *((uint64_t *)dst + index) = (uint64_t)round(value); + break; + default: + assert(0); + } + } + } +} + + +void +random_elem(union lp_type type, void *dst, unsigned index) +{ + assert(index < type.length); + if (type.floating) { + double value = (double)random()/(double)RAND_MAX; + if(!type.norm) + value += (double)random(); + if(type.sign) + if(random() & 1) + value = -value; + switch(type.width) { + case 32: + *((float *)dst + index) = (float)value; + break; + case 64: + *((double *)dst + index) = value; + break; + default: + assert(0); + } + } + else { + switch(type.width) { + case 8: + *((uint8_t *)dst + index) = (uint8_t)random(); + break; + case 16: + *((uint16_t *)dst + index) = (uint16_t)random(); + break; + case 32: + *((uint32_t *)dst + index) = (uint32_t)random(); + break; + case 64: + *((uint64_t *)dst + index) = (uint64_t)random(); + break; + default: + assert(0); + } + } +} + + +void +read_vec(union lp_type type, const void *src, double *dst) +{ + unsigned i; + for (i = 0; i < type.length; ++i) + dst[i] = read_elem(type, src, i); +} + + +void +write_vec(union lp_type type, void *dst, const double *src) +{ + unsigned i; + for (i = 0; i < type.length; ++i) + write_elem(type, dst, i, src[i]); +} + + +float +random_float(void) +{ + return (float)((double)random()/(double)RAND_MAX); +} + + +void +random_vec(union lp_type type, void *dst) +{ + unsigned i; + for (i = 0; i < type.length; ++i) + random_elem(type, dst, i); +} + + +boolean +compare_vec(union lp_type type, const void *res, const double *ref) +{ + double eps; + unsigned i; + + if (type.floating) { + switch(type.width) { + case 32: + eps = FLT_EPSILON; + break; + case 64: + eps = DBL_EPSILON; + break; + default: + assert(0); + eps = 0.0; + break; + } + } + else { + double scale = lp_const_scale(type); + eps = 1.0/scale; + } + + for (i = 0; i < type.length; ++i) { + double res_elem = read_elem(type, res, i); + double ref_elem = ref[i]; + double delta = fabs(res_elem - ref_elem); + if(delta >= 2.0*eps) + return FALSE; + } + + return TRUE; +} + + +void +dump_vec(FILE *fp, union lp_type type, const void *src) +{ + unsigned i; + for (i = 0; i < type.length; ++i) { + if(i) + fprintf(fp, " "); + if (type.floating) { + double value; + switch(type.width) { + case 32: + value = *((const float *)src + i); + break; + case 64: + value = *((const double *)src + i); + break; + default: + assert(0); + value = 0.0; + } + fprintf(fp, "%f", value); + } + else { + if(type.sign) { + long long value; + const char *format; + switch(type.width) { + case 8: + value = *((const int8_t *)src + i); + format = "%3lli"; + break; + case 16: + value = *((const int16_t *)src + i); + format = "%5lli"; + break; + case 32: + value = *((const int32_t *)src + i); + format = "%10lli"; + break; + case 64: + value = *((const int64_t *)src + i); + format = "%20lli"; + break; + default: + assert(0); + value = 0.0; + format = "?"; + } + fprintf(fp, format, value); + } + else { + unsigned long long value; + const char *format; + switch(type.width) { + case 8: + value = *((const uint8_t *)src + i); + format = "%4llu"; + break; + case 16: + value = *((const uint16_t *)src + i); + format = "%6llu"; + break; + case 32: + value = *((const uint32_t *)src + i); + format = "%11llu"; + break; + case 64: + value = *((const uint64_t *)src + i); + format = "%21llu"; + break; + default: + assert(0); + value = 0.0; + format = "?"; + } + fprintf(fp, format, value); + } + } + } +} + + +int main(int argc, char **argv) +{ + unsigned verbose = 0; + FILE *fp = NULL; + unsigned long n = 1000; + unsigned i; + boolean success; + + for(i = 1; i < argc; ++i) { + if(strcmp(argv[i], "-v") == 0) + ++verbose; + else if(strcmp(argv[i], "-o") == 0) + fp = fopen(argv[++i], "wt"); + else + n = atoi(argv[i]); + } + + if(fp) { + /* Warm up the caches */ + test_some(0, NULL, 100); + + write_tsv_header(fp); + } + + if(n) + success = test_some(verbose, fp, n); + else + success = test_all(verbose, fp); + + if(fp) + fclose(fp); + + return success ? 0 : 1; +} -- cgit v1.2.3