1 /************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29 #include <stdlib.h> 30 #include <stdio.h> 31 #include <float.h> 32 33 #include "util/u_memory.h" 34 #include "util/u_pointer.h" 35 #include "util/u_string.h" 36 #include "util/u_format.h" 37 #include "util/u_format_tests.h" 38 #include "util/u_format_s3tc.h" 39 40 #include "gallivm/lp_bld.h" 41 #include "gallivm/lp_bld_debug.h" 42 #include "gallivm/lp_bld_format.h" 43 #include "gallivm/lp_bld_init.h" 44 45 #include "lp_test.h" 46 47 48 void 49 write_tsv_header(FILE *fp) 50 { 51 fprintf(fp, 52 "result\t" 53 "format\n"); 54 55 fflush(fp); 56 } 57 58 59 static void 60 write_tsv_row(FILE *fp, 61 const struct util_format_description *desc, 62 boolean success) 63 { 64 fprintf(fp, "%s\t", success ? "pass" : "fail"); 65 66 fprintf(fp, "%s\n", desc->name); 67 68 fflush(fp); 69 } 70 71 72 typedef void 73 (*fetch_ptr_t)(void *unpacked, const void *packed, 74 unsigned i, unsigned j); 75 76 77 static LLVMValueRef 78 add_fetch_rgba_test(struct gallivm_state *gallivm, unsigned verbose, 79 const struct util_format_description *desc, 80 struct lp_type type) 81 { 82 char name[256]; 83 LLVMContextRef context = gallivm->context; 84 LLVMModuleRef module = gallivm->module; 85 LLVMBuilderRef builder = gallivm->builder; 86 LLVMTypeRef args[4]; 87 LLVMValueRef func; 88 LLVMValueRef packed_ptr; 89 LLVMValueRef offset = LLVMConstNull(LLVMInt32TypeInContext(context)); 90 LLVMValueRef rgba_ptr; 91 LLVMValueRef i; 92 LLVMValueRef j; 93 LLVMBasicBlockRef block; 94 LLVMValueRef rgba; 95 96 util_snprintf(name, sizeof name, "fetch_%s_%s", desc->short_name, 97 type.floating ? "float" : "unorm8"); 98 99 args[0] = LLVMPointerType(lp_build_vec_type(gallivm, type), 0); 100 args[1] = LLVMPointerType(LLVMInt8TypeInContext(context), 0); 101 args[3] = args[2] = LLVMInt32TypeInContext(context); 102 103 func = LLVMAddFunction(module, name, 104 LLVMFunctionType(LLVMVoidTypeInContext(context), 105 args, Elements(args), 0)); 106 LLVMSetFunctionCallConv(func, LLVMCCallConv); 107 rgba_ptr = LLVMGetParam(func, 0); 108 packed_ptr = LLVMGetParam(func, 1); 109 i = LLVMGetParam(func, 2); 110 j = LLVMGetParam(func, 3); 111 112 block = LLVMAppendBasicBlockInContext(context, func, "entry"); 113 LLVMPositionBuilderAtEnd(builder, block); 114 115 rgba = lp_build_fetch_rgba_aos(gallivm, desc, type, 116 packed_ptr, offset, i, j); 117 118 LLVMBuildStore(builder, rgba, rgba_ptr); 119 120 LLVMBuildRetVoid(builder); 121 122 gallivm_verify_function(gallivm, func); 123 124 return func; 125 } 126 127 128 PIPE_ALIGN_STACK 129 static boolean 130 test_format_float(unsigned verbose, FILE *fp, 131 const struct util_format_description *desc) 132 { 133 struct gallivm_state *gallivm; 134 LLVMValueRef fetch = NULL; 135 fetch_ptr_t fetch_ptr; 136 PIPE_ALIGN_VAR(16) float unpacked[4]; 137 boolean first = TRUE; 138 boolean success = TRUE; 139 unsigned i, j, k, l; 140 141 gallivm = gallivm_create(); 142 143 fetch = add_fetch_rgba_test(gallivm, verbose, desc, lp_float32_vec4_type()); 144 145 gallivm_compile_module(gallivm); 146 147 fetch_ptr = (fetch_ptr_t) gallivm_jit_function(gallivm, fetch); 148 149 for (l = 0; l < util_format_nr_test_cases; ++l) { 150 const struct util_format_test_case *test = &util_format_test_cases[l]; 151 152 if (test->format == desc->format) { 153 154 if (first) { 155 printf("Testing %s (float) ...\n", 156 desc->name); 157 first = FALSE; 158 } 159 160 for (i = 0; i < desc->block.height; ++i) { 161 for (j = 0; j < desc->block.width; ++j) { 162 boolean match = TRUE; 163 164 memset(unpacked, 0, sizeof unpacked); 165 166 fetch_ptr(unpacked, test->packed, j, i); 167 168 for(k = 0; k < 4; ++k) { 169 if (util_double_inf_sign(test->unpacked[i][j][k]) != util_inf_sign(unpacked[k])) { 170 match = FALSE; 171 } 172 173 if (util_is_double_nan(test->unpacked[i][j][k]) != util_is_nan(unpacked[k])) { 174 match = FALSE; 175 } 176 177 if (!util_is_double_inf_or_nan(test->unpacked[i][j][k]) && 178 fabs((float)test->unpacked[i][j][k] - unpacked[k]) > FLT_EPSILON) { 179 match = FALSE; 180 } 181 } 182 183 if (!match) { 184 printf("FAILED\n"); 185 printf(" Packed: %02x %02x %02x %02x\n", 186 test->packed[0], test->packed[1], test->packed[2], test->packed[3]); 187 printf(" Unpacked (%u,%u): %.9g %.9g %.9g %.9g obtained\n", 188 j, i, 189 unpacked[0], unpacked[1], unpacked[2], unpacked[3]); 190 printf(" %.9g %.9g %.9g %.9g expected\n", 191 test->unpacked[i][j][0], 192 test->unpacked[i][j][1], 193 test->unpacked[i][j][2], 194 test->unpacked[i][j][3]); 195 success = FALSE; 196 } 197 } 198 } 199 } 200 } 201 202 gallivm_free_function(gallivm, fetch, fetch_ptr); 203 204 gallivm_destroy(gallivm); 205 206 if(fp) 207 write_tsv_row(fp, desc, success); 208 209 return success; 210 } 211 212 213 PIPE_ALIGN_STACK 214 static boolean 215 test_format_unorm8(unsigned verbose, FILE *fp, 216 const struct util_format_description *desc) 217 { 218 struct gallivm_state *gallivm; 219 LLVMValueRef fetch = NULL; 220 fetch_ptr_t fetch_ptr; 221 uint8_t unpacked[4]; 222 boolean first = TRUE; 223 boolean success = TRUE; 224 unsigned i, j, k, l; 225 226 gallivm = gallivm_create(); 227 228 fetch = add_fetch_rgba_test(gallivm, verbose, desc, lp_unorm8_vec4_type()); 229 230 gallivm_compile_module(gallivm); 231 232 fetch_ptr = (fetch_ptr_t) gallivm_jit_function(gallivm, fetch); 233 234 for (l = 0; l < util_format_nr_test_cases; ++l) { 235 const struct util_format_test_case *test = &util_format_test_cases[l]; 236 237 if (test->format == desc->format) { 238 239 if (first) { 240 printf("Testing %s (unorm8) ...\n", 241 desc->name); 242 first = FALSE; 243 } 244 245 for (i = 0; i < desc->block.height; ++i) { 246 for (j = 0; j < desc->block.width; ++j) { 247 boolean match; 248 249 memset(unpacked, 0, sizeof unpacked); 250 251 fetch_ptr(unpacked, test->packed, j, i); 252 253 match = TRUE; 254 for(k = 0; k < 4; ++k) { 255 int error = float_to_ubyte(test->unpacked[i][j][k]) - unpacked[k]; 256 257 if (util_is_double_nan(test->unpacked[i][j][k])) 258 continue; 259 260 if (error < 0) 261 error = -error; 262 263 if (error > 1) 264 match = FALSE; 265 } 266 267 if (!match) { 268 printf("FAILED\n"); 269 printf(" Packed: %02x %02x %02x %02x\n", 270 test->packed[0], test->packed[1], test->packed[2], test->packed[3]); 271 printf(" Unpacked (%u,%u): %02x %02x %02x %02x obtained\n", 272 j, i, 273 unpacked[0], unpacked[1], unpacked[2], unpacked[3]); 274 printf(" %02x %02x %02x %02x expected\n", 275 float_to_ubyte(test->unpacked[i][j][0]), 276 float_to_ubyte(test->unpacked[i][j][1]), 277 float_to_ubyte(test->unpacked[i][j][2]), 278 float_to_ubyte(test->unpacked[i][j][3])); 279 280 success = FALSE; 281 } 282 } 283 } 284 } 285 } 286 287 gallivm_free_function(gallivm, fetch, fetch_ptr); 288 289 gallivm_destroy(gallivm); 290 291 if(fp) 292 write_tsv_row(fp, desc, success); 293 294 return success; 295 } 296 297 298 299 300 static boolean 301 test_one(unsigned verbose, FILE *fp, 302 const struct util_format_description *format_desc) 303 { 304 boolean success = TRUE; 305 306 if (!test_format_float(verbose, fp, format_desc)) { 307 success = FALSE; 308 } 309 310 if (!test_format_unorm8(verbose, fp, format_desc)) { 311 success = FALSE; 312 } 313 314 return success; 315 } 316 317 318 boolean 319 test_all(unsigned verbose, FILE *fp) 320 { 321 enum pipe_format format; 322 boolean success = TRUE; 323 324 util_format_s3tc_init(); 325 326 for (format = 1; format < PIPE_FORMAT_COUNT; ++format) { 327 const struct util_format_description *format_desc; 328 329 format_desc = util_format_description(format); 330 if (!format_desc) { 331 continue; 332 } 333 334 335 /* 336 * TODO: test more 337 */ 338 339 if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { 340 continue; 341 } 342 343 if (util_format_is_pure_integer(format)) 344 continue; 345 346 if (format_desc->layout == UTIL_FORMAT_LAYOUT_S3TC && 347 !util_format_s3tc_enabled) { 348 continue; 349 } 350 351 if (!test_one(verbose, fp, format_desc)) { 352 success = FALSE; 353 } 354 } 355 356 return success; 357 } 358 359 360 boolean 361 test_some(unsigned verbose, FILE *fp, 362 unsigned long n) 363 { 364 return test_all(verbose, fp); 365 } 366 367 368 boolean 369 test_single(unsigned verbose, FILE *fp) 370 { 371 printf("no test_single()"); 372 return TRUE; 373 } 374