X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_test_format.c;h=31d965de59725089064203996ec307d43e0992a7;hb=dffeaa55dd1155d7a1e8feb5ecfc54fff688fcd8;hp=48828bd0a0f6e4a56e2168b72f3388d08f8e0aee;hpb=c61bf363937f40624a5632745630d4f2b9907082;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_test_format.c b/src/gallium/drivers/llvmpipe/lp_test_format.c index 48828bd0a0f..31d965de597 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_format.c +++ b/src/gallium/drivers/llvmpipe/lp_test_format.c @@ -28,67 +28,23 @@ #include #include +#include -#include -#include -#include -#include -#include - -#include "util/u_cpu_detect.h" +#include "util/u_memory.h" +#include "util/u_pointer.h" +#include "util/u_string.h" #include "util/u_format.h" +#include "util/u_format_tests.h" +#include "util/u_format_s3tc.h" +#include "gallivm/lp_bld.h" +#include "gallivm/lp_bld_debug.h" #include "gallivm/lp_bld_format.h" -#include "lp_test.h" - - -struct pixel_test_case -{ - enum pipe_format format; - uint32_t packed; - double unpacked[4]; -}; +#include "gallivm/lp_bld_init.h" +#include "lp_test.h" -struct pixel_test_case test_cases[] = -{ - {PIPE_FORMAT_R5G6B5_UNORM, 0x0000, {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R5G6B5_UNORM, 0x001f, {0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_R5G6B5_UNORM, 0x07e0, {0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R5G6B5_UNORM, 0xf800, {1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R5G6B5_UNORM, 0xffff, {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_A1R5G5B5_UNORM, 0x0000, {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_A1R5G5B5_UNORM, 0x001f, {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_A1R5G5B5_UNORM, 0x03e0, {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_A1R5G5B5_UNORM, 0x7c00, {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_A1R5G5B5_UNORM, 0x8000, {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_A1R5G5B5_UNORM, 0xffff, {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_A8R8G8B8_UNORM, 0x00000000, {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_A8R8G8B8_UNORM, 0x000000ff, {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_A8R8G8B8_UNORM, 0x0000ff00, {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_A8R8G8B8_UNORM, 0x00ff0000, {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_A8R8G8B8_UNORM, 0xff000000, {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_A8R8G8B8_UNORM, 0xffffffff, {1.0, 1.0, 1.0, 1.0}}, - -#if 0 - {PIPE_FORMAT_R8G8B8A8_UNORM, 0x00000000, {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_UNORM, 0x000000ff, {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8A8_UNORM, 0x0000ff00, {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_UNORM, 0x00ff0000, {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_UNORM, 0xff000000, {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_UNORM, 0xffffffff, {1.0, 1.0, 1.0, 1.0}}, -#endif - - {PIPE_FORMAT_B8G8R8A8_UNORM, 0x00000000, {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_B8G8R8A8_UNORM, 0x000000ff, {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_B8G8R8A8_UNORM, 0x0000ff00, {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_B8G8R8A8_UNORM, 0x00ff0000, {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_B8G8R8A8_UNORM, 0xff000000, {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_B8G8R8A8_UNORM, 0xffffffff, {1.0, 1.0, 1.0, 1.0}}, -}; - +static struct lp_build_format_cache *cache_ptr; void write_tsv_header(FILE *fp) @@ -114,181 +70,287 @@ write_tsv_row(FILE *fp, } -typedef void (*load_ptr_t)(const uint32_t packed, float *); +typedef void +(*fetch_ptr_t)(void *unpacked, const void *packed, + unsigned i, unsigned j, struct lp_build_format_cache *cache); static LLVMValueRef -add_load_rgba_test(LLVMModuleRef module, - const struct util_format_description *desc) +add_fetch_rgba_test(struct gallivm_state *gallivm, unsigned verbose, + const struct util_format_description *desc, + struct lp_type type, + unsigned use_cache) { - LLVMTypeRef args[2]; + char name[256]; + LLVMContextRef context = gallivm->context; + LLVMModuleRef module = gallivm->module; + LLVMBuilderRef builder = gallivm->builder; + LLVMTypeRef args[5]; LLVMValueRef func; - LLVMValueRef packed; + LLVMValueRef packed_ptr; + LLVMValueRef offset = LLVMConstNull(LLVMInt32TypeInContext(context)); LLVMValueRef rgba_ptr; + LLVMValueRef i; + LLVMValueRef j; LLVMBasicBlockRef block; - LLVMBuilderRef builder; LLVMValueRef rgba; + LLVMValueRef cache = NULL; - args[0] = LLVMInt32Type(); - args[1] = LLVMPointerType(LLVMVectorType(LLVMFloatType(), 4), 0); + snprintf(name, sizeof name, "fetch_%s_%s", desc->short_name, + type.floating ? "float" : "unorm8"); - func = LLVMAddFunction(module, "load", LLVMFunctionType(LLVMVoidType(), args, 2, 0)); + args[0] = LLVMPointerType(lp_build_vec_type(gallivm, type), 0); + args[1] = LLVMPointerType(LLVMInt8TypeInContext(context), 0); + args[3] = args[2] = LLVMInt32TypeInContext(context); + args[4] = LLVMPointerType(lp_build_format_cache_type(gallivm), 0); + + func = LLVMAddFunction(module, name, + LLVMFunctionType(LLVMVoidTypeInContext(context), + args, ARRAY_SIZE(args), 0)); LLVMSetFunctionCallConv(func, LLVMCCallConv); - packed = LLVMGetParam(func, 0); - rgba_ptr = LLVMGetParam(func, 1); + rgba_ptr = LLVMGetParam(func, 0); + packed_ptr = LLVMGetParam(func, 1); + i = LLVMGetParam(func, 2); + j = LLVMGetParam(func, 3); - block = LLVMAppendBasicBlock(func, "entry"); - builder = LLVMCreateBuilder(); - LLVMPositionBuilderAtEnd(builder, block); + if (use_cache) { + cache = LLVMGetParam(func, 4); + } - if(desc->block.bits < 32) - packed = LLVMBuildTrunc(builder, packed, LLVMIntType(desc->block.bits), ""); + block = LLVMAppendBasicBlockInContext(context, func, "entry"); + LLVMPositionBuilderAtEnd(builder, block); - rgba = lp_build_unpack_rgba_aos(builder, desc, packed); + rgba = lp_build_fetch_rgba_aos(gallivm, desc, type, TRUE, + packed_ptr, offset, i, j, cache); LLVMBuildStore(builder, rgba, rgba_ptr); LLVMBuildRetVoid(builder); - LLVMDisposeBuilder(builder); + gallivm_verify_function(gallivm, func); + return func; } -typedef void (*store_ptr_t)(uint32_t *, const float *); - - -static LLVMValueRef -add_store_rgba_test(LLVMModuleRef module, - const struct util_format_description *desc) +PIPE_ALIGN_STACK +static boolean +test_format_float(unsigned verbose, FILE *fp, + const struct util_format_description *desc, + unsigned use_cache) { - LLVMTypeRef args[2]; - LLVMValueRef func; - LLVMValueRef packed_ptr; - LLVMValueRef rgba_ptr; - LLVMBasicBlockRef block; - LLVMBuilderRef builder; - LLVMValueRef rgba; - LLVMValueRef packed; + LLVMContextRef context; + struct gallivm_state *gallivm; + LLVMValueRef fetch = NULL; + fetch_ptr_t fetch_ptr; + PIPE_ALIGN_VAR(16) uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES]; + PIPE_ALIGN_VAR(16) float unpacked[4]; + boolean first = TRUE; + boolean success = TRUE; + unsigned i, j, k, l; + + context = LLVMContextCreate(); + gallivm = gallivm_create("test_module_float", context); + + fetch = add_fetch_rgba_test(gallivm, verbose, desc, + lp_float32_vec4_type(), use_cache); + + gallivm_compile_module(gallivm); + + fetch_ptr = (fetch_ptr_t) gallivm_jit_function(gallivm, fetch); + + gallivm_free_ir(gallivm); + + for (l = 0; l < util_format_nr_test_cases; ++l) { + const struct util_format_test_case *test = &util_format_test_cases[l]; + + if (test->format == desc->format) { + + if (first) { + printf("Testing %s (float) ...\n", + desc->name); + fflush(stdout); + first = FALSE; + } + + /* To ensure it's 16-byte aligned */ + memcpy(packed, test->packed, sizeof packed); + + for (i = 0; i < desc->block.height; ++i) { + for (j = 0; j < desc->block.width; ++j) { + boolean match = TRUE; + + memset(unpacked, 0, sizeof unpacked); + + fetch_ptr(unpacked, packed, j, i, use_cache ? cache_ptr : NULL); + + for(k = 0; k < 4; ++k) { + if (util_double_inf_sign(test->unpacked[i][j][k]) != util_inf_sign(unpacked[k])) { + match = FALSE; + } + + if (util_is_double_nan(test->unpacked[i][j][k]) != util_is_nan(unpacked[k])) { + match = FALSE; + } + + if (!util_is_double_inf_or_nan(test->unpacked[i][j][k]) && + fabs((float)test->unpacked[i][j][k] - unpacked[k]) > FLT_EPSILON) { + match = FALSE; + } + } + + /* Ignore errors in S3TC for now */ + if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { + match = TRUE; + } + + if (!match) { + printf("FAILED\n"); + printf(" Packed: %02x %02x %02x %02x\n", + test->packed[0], test->packed[1], test->packed[2], test->packed[3]); + printf(" Unpacked (%u,%u): %.9g %.9g %.9g %.9g obtained\n", + j, i, + unpacked[0], unpacked[1], unpacked[2], unpacked[3]); + printf(" %.9g %.9g %.9g %.9g expected\n", + test->unpacked[i][j][0], + test->unpacked[i][j][1], + test->unpacked[i][j][2], + test->unpacked[i][j][3]); + fflush(stdout); + success = FALSE; + } + } + } + } + } - args[0] = LLVMPointerType(LLVMInt32Type(), 0); - args[1] = LLVMPointerType(LLVMVectorType(LLVMFloatType(), 4), 0); + gallivm_destroy(gallivm); + LLVMContextDispose(context); - func = LLVMAddFunction(module, "store", LLVMFunctionType(LLVMVoidType(), args, 2, 0)); - LLVMSetFunctionCallConv(func, LLVMCCallConv); - packed_ptr = LLVMGetParam(func, 0); - rgba_ptr = LLVMGetParam(func, 1); - - block = LLVMAppendBasicBlock(func, "entry"); - builder = LLVMCreateBuilder(); - LLVMPositionBuilderAtEnd(builder, block); + if(fp) + write_tsv_row(fp, desc, success); - rgba = LLVMBuildLoad(builder, rgba_ptr, ""); + return success; +} - packed = lp_build_pack_rgba_aos(builder, desc, rgba); - if(desc->block.bits < 32) - packed = LLVMBuildZExt(builder, packed, LLVMInt32Type(), ""); +PIPE_ALIGN_STACK +static boolean +test_format_unorm8(unsigned verbose, FILE *fp, + const struct util_format_description *desc, + unsigned use_cache) +{ + LLVMContextRef context; + struct gallivm_state *gallivm; + LLVMValueRef fetch = NULL; + fetch_ptr_t fetch_ptr; + PIPE_ALIGN_VAR(16) uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES]; + uint8_t unpacked[4]; + boolean first = TRUE; + boolean success = TRUE; + unsigned i, j, k, l; + + context = LLVMContextCreate(); + gallivm = gallivm_create("test_module_unorm8", context); + + fetch = add_fetch_rgba_test(gallivm, verbose, desc, + lp_unorm8_vec4_type(), use_cache); + + gallivm_compile_module(gallivm); + + fetch_ptr = (fetch_ptr_t) gallivm_jit_function(gallivm, fetch); + + gallivm_free_ir(gallivm); + + for (l = 0; l < util_format_nr_test_cases; ++l) { + const struct util_format_test_case *test = &util_format_test_cases[l]; + + if (test->format == desc->format) { + + if (first) { + printf("Testing %s (unorm8) ...\n", + desc->name); + first = FALSE; + } + + /* To ensure it's 16-byte aligned */ + /* Could skip this and use unaligned lp_build_fetch_rgba_aos */ + memcpy(packed, test->packed, sizeof packed); + + for (i = 0; i < desc->block.height; ++i) { + for (j = 0; j < desc->block.width; ++j) { + boolean match; + + memset(unpacked, 0, sizeof unpacked); + + fetch_ptr(unpacked, packed, j, i, use_cache ? cache_ptr : NULL); + + match = TRUE; + for(k = 0; k < 4; ++k) { + int error = float_to_ubyte(test->unpacked[i][j][k]) - unpacked[k]; + + if (util_is_double_nan(test->unpacked[i][j][k])) + continue; + + if (error < 0) + error = -error; + + if (error > 1) + match = FALSE; + } + + /* Ignore errors in S3TC as we only implement a poor man approach */ + if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { + match = TRUE; + } + + if (!match) { + printf("FAILED\n"); + printf(" Packed: %02x %02x %02x %02x\n", + test->packed[0], test->packed[1], test->packed[2], test->packed[3]); + printf(" Unpacked (%u,%u): %02x %02x %02x %02x obtained\n", + j, i, + unpacked[0], unpacked[1], unpacked[2], unpacked[3]); + printf(" %02x %02x %02x %02x expected\n", + float_to_ubyte(test->unpacked[i][j][0]), + float_to_ubyte(test->unpacked[i][j][1]), + float_to_ubyte(test->unpacked[i][j][2]), + float_to_ubyte(test->unpacked[i][j][3])); + + success = FALSE; + } + } + } + } + } - LLVMBuildStore(builder, packed, packed_ptr); + gallivm_destroy(gallivm); + LLVMContextDispose(context); - LLVMBuildRetVoid(builder); + if(fp) + write_tsv_row(fp, desc, success); - LLVMDisposeBuilder(builder); - return func; + return success; } -PIPE_ALIGN_STACK + + static boolean -test_format(unsigned verbose, FILE *fp, const struct pixel_test_case *test) +test_one(unsigned verbose, FILE *fp, + const struct util_format_description *format_desc, + unsigned use_cache) { - LLVMModuleRef module = NULL; - LLVMValueRef load = NULL; - LLVMValueRef store = NULL; - LLVMExecutionEngineRef engine = NULL; - LLVMModuleProviderRef provider = NULL; - LLVMPassManagerRef pass = NULL; - char *error = NULL; - const struct util_format_description *desc; - load_ptr_t load_ptr; - store_ptr_t store_ptr; - float unpacked[4]; - unsigned packed; - boolean success; - unsigned i; - - desc = util_format_description(test->format); - fprintf(stderr, "%s\n", desc->name); - - module = LLVMModuleCreateWithName("test"); - - load = add_load_rgba_test(module, desc); - store = add_store_rgba_test(module, desc); - - if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) { - LLVMDumpModule(module); - abort(); - } - LLVMDisposeMessage(error); + boolean success = TRUE; - provider = LLVMCreateModuleProviderForExistingModule(module); - if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) { - fprintf(stderr, "%s\n", error); - LLVMDisposeMessage(error); - abort(); + if (!test_format_float(verbose, fp, format_desc, use_cache)) { + success = FALSE; } -#if 0 - pass = LLVMCreatePassManager(); - LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); - /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, - * but there are more on SVN. */ - LLVMAddConstantPropagationPass(pass); - LLVMAddInstructionCombiningPass(pass); - LLVMAddPromoteMemoryToRegisterPass(pass); - LLVMAddGVNPass(pass); - LLVMAddCFGSimplificationPass(pass); - LLVMRunPassManager(pass, module); -#else - (void)pass; -#endif - - load_ptr = (load_ptr_t) LLVMGetPointerToGlobal(engine, load); - store_ptr = (store_ptr_t)LLVMGetPointerToGlobal(engine, store); - - memset(unpacked, 0, sizeof unpacked); - packed = 0; - - load_ptr(test->packed, unpacked); - store_ptr(&packed, unpacked); - - success = TRUE; - if(test->packed != packed) - success = FALSE; - for(i = 0; i < 4; ++i) - if(test->unpacked[i] != unpacked[i]) - success = FALSE; - - if (!success) { - printf("FAILED\n"); - printf(" Packed: %08x\n", test->packed); - printf(" %08x\n", packed); - printf(" Unpacked: %f %f %f %f\n", unpacked[0], unpacked[1], unpacked[2], unpacked[3]); - printf(" %f %f %f %f\n", test->unpacked[0], test->unpacked[1], test->unpacked[2], test->unpacked[3]); - LLVMDumpModule(module); + if (!test_format_unorm8(verbose, fp, format_desc, use_cache)) { + success = FALSE; } - LLVMFreeMachineCodeForFunction(engine, store); - LLVMFreeMachineCodeForFunction(engine, load); - - LLVMDisposeExecutionEngine(engine); - if(pass) - LLVMDisposePassManager(pass); - - if(fp) - write_tsv_row(fp, desc, success); - return success; } @@ -296,19 +358,71 @@ test_format(unsigned verbose, FILE *fp, const struct pixel_test_case *test) boolean test_all(unsigned verbose, FILE *fp) { - unsigned i; - bool success = TRUE; - - for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) - if(!test_format(verbose, fp, &test_cases[i])) - success = FALSE; + enum pipe_format format; + boolean success = TRUE; + unsigned use_cache; + + cache_ptr = align_malloc(sizeof(struct lp_build_format_cache), 16); + + for (use_cache = 0; use_cache < 2; use_cache++) { + for (format = 1; format < PIPE_FORMAT_COUNT; ++format) { + const struct util_format_description *format_desc; + + format_desc = util_format_description(format); + if (!format_desc) { + continue; + } + + /* + * TODO: test more + */ + + if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { + continue; + } + + if (util_format_is_pure_integer(format)) + continue; + + /* only have util fetch func for etc1 */ + if (format_desc->layout == UTIL_FORMAT_LAYOUT_ETC && + format != PIPE_FORMAT_ETC1_RGB8) { + continue; + } + + /* missing fetch funcs */ + if (format_desc->layout == UTIL_FORMAT_LAYOUT_ASTC || + format_desc->layout == UTIL_FORMAT_LAYOUT_ATC) { + continue; + } + + /* only test twice with formats which can use cache */ + if (format_desc->layout != UTIL_FORMAT_LAYOUT_S3TC && use_cache) { + continue; + } + + if (!test_one(verbose, fp, format_desc, use_cache)) { + success = FALSE; + } + } + } + align_free(cache_ptr); return success; } boolean -test_some(unsigned verbose, FILE *fp, unsigned long n) +test_some(unsigned verbose, FILE *fp, + unsigned long n) { return test_all(verbose, fp); } + + +boolean +test_single(unsigned verbose, FILE *fp) +{ + printf("no test_single()"); + return TRUE; +}