Merge branch 'gallium-newclear'
[mesa.git] / src / gallium / drivers / llvmpipe / lp_test_format.c
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 "gallivm/lp_bld.h"
34 #include "gallivm/lp_bld_init.h"
35 #include <llvm-c/Analysis.h>
36 #include <llvm-c/Target.h>
37 #include <llvm-c/Transforms/Scalar.h>
38
39 #include "util/u_memory.h"
40 #include "util/u_pointer.h"
41 #include "util/u_format.h"
42 #include "util/u_format_tests.h"
43 #include "util/u_format_s3tc.h"
44
45 #include "gallivm/lp_bld_format.h"
46 #include "lp_test.h"
47
48
49 void
50 write_tsv_header(FILE *fp)
51 {
52 fprintf(fp,
53 "result\t"
54 "format\n");
55
56 fflush(fp);
57 }
58
59
60 static void
61 write_tsv_row(FILE *fp,
62 const struct util_format_description *desc,
63 boolean success)
64 {
65 fprintf(fp, "%s\t", success ? "pass" : "fail");
66
67 fprintf(fp, "%s\n", desc->name);
68
69 fflush(fp);
70 }
71
72
73 typedef void
74 (*fetch_ptr_t)(float *, const void *packed,
75 unsigned i, unsigned j);
76
77
78 static LLVMValueRef
79 add_fetch_rgba_test(LLVMModuleRef lp_build_module,
80 const struct util_format_description *desc)
81 {
82 LLVMTypeRef args[4];
83 LLVMValueRef func;
84 LLVMValueRef packed_ptr;
85 LLVMValueRef rgba_ptr;
86 LLVMValueRef i;
87 LLVMValueRef j;
88 LLVMBasicBlockRef block;
89 LLVMBuilderRef builder;
90 LLVMValueRef rgba;
91
92 args[0] = LLVMPointerType(LLVMVectorType(LLVMFloatType(), 4), 0);
93 args[1] = LLVMPointerType(LLVMInt8Type(), 0);
94 args[3] = args[2] = LLVMInt32Type();
95
96 func = LLVMAddFunction(lp_build_module, "fetch", LLVMFunctionType(LLVMVoidType(), args, Elements(args), 0));
97 LLVMSetFunctionCallConv(func, LLVMCCallConv);
98 rgba_ptr = LLVMGetParam(func, 0);
99 packed_ptr = LLVMGetParam(func, 1);
100 i = LLVMGetParam(func, 2);
101 j = LLVMGetParam(func, 3);
102
103 block = LLVMAppendBasicBlock(func, "entry");
104 builder = LLVMCreateBuilder();
105 LLVMPositionBuilderAtEnd(builder, block);
106
107 rgba = lp_build_fetch_rgba_aos(builder, desc, packed_ptr, i, j);
108
109 LLVMBuildStore(builder, rgba, rgba_ptr);
110
111 LLVMBuildRetVoid(builder);
112
113 LLVMDisposeBuilder(builder);
114 return func;
115 }
116
117
118 PIPE_ALIGN_STACK
119 static boolean
120 test_format(unsigned verbose, FILE *fp,
121 const struct util_format_description *desc,
122 const struct util_format_test_case *test)
123 {
124 LLVMValueRef fetch = NULL;
125 LLVMPassManagerRef pass = NULL;
126 fetch_ptr_t fetch_ptr;
127 PIPE_ALIGN_VAR(16) float unpacked[4];
128 boolean success;
129 unsigned i, j, k;
130
131 fetch = add_fetch_rgba_test(lp_build_module, desc);
132
133 if (LLVMVerifyFunction(fetch, LLVMPrintMessageAction)) {
134 LLVMDumpValue(fetch);
135 abort();
136 }
137
138 #if 0
139 pass = LLVMCreatePassManager();
140 LLVMAddTargetData(LLVMGetExecutionEngineTargetData(lp_build_engine), pass);
141 /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
142 * but there are more on SVN. */
143 LLVMAddConstantPropagationPass(pass);
144 LLVMAddInstructionCombiningPass(pass);
145 LLVMAddPromoteMemoryToRegisterPass(pass);
146 LLVMAddGVNPass(pass);
147 LLVMAddCFGSimplificationPass(pass);
148 LLVMRunPassManager(pass, lp_build_module);
149 #else
150 (void)pass;
151 #endif
152
153 fetch_ptr = (fetch_ptr_t)pointer_to_func(LLVMGetPointerToGlobal(lp_build_engine, fetch));
154
155 for (i = 0; i < desc->block.height; ++i) {
156 for (j = 0; j < desc->block.width; ++j) {
157
158 memset(unpacked, 0, sizeof unpacked);
159
160 fetch_ptr(unpacked, test->packed, j, i);
161
162 success = TRUE;
163 for(k = 0; k < 4; ++k)
164 if (fabs((float)test->unpacked[i][j][k] - unpacked[k]) > FLT_EPSILON)
165 success = FALSE;
166
167 if (!success) {
168 printf("FAILED\n");
169 printf(" Packed: %02x %02x %02x %02x\n",
170 test->packed[0], test->packed[1], test->packed[2], test->packed[3]);
171 printf(" Unpacked (%u,%u): %f %f %f %f obtained\n",
172 j, i,
173 unpacked[0], unpacked[1], unpacked[2], unpacked[3]);
174 printf(" %f %f %f %f expected\n",
175 test->unpacked[i][j][0],
176 test->unpacked[i][j][1],
177 test->unpacked[i][j][2],
178 test->unpacked[i][j][3]);
179 }
180 }
181 }
182
183 if (!success)
184 LLVMDumpValue(fetch);
185
186 LLVMFreeMachineCodeForFunction(lp_build_engine, fetch);
187 LLVMDeleteFunction(fetch);
188
189 if(pass)
190 LLVMDisposePassManager(pass);
191
192 if(fp)
193 write_tsv_row(fp, desc, success);
194
195 return success;
196 }
197
198
199
200 static boolean
201 test_one(unsigned verbose, FILE *fp,
202 const struct util_format_description *format_desc)
203 {
204 unsigned i;
205 boolean first = TRUE;
206 boolean success = TRUE;
207
208 for (i = 0; i < util_format_nr_test_cases; ++i) {
209 const struct util_format_test_case *test = &util_format_test_cases[i];
210
211 if (test->format == format_desc->format) {
212
213 if (first) {
214 printf("Testing %s ...\n",
215 format_desc->name);
216 first = FALSE;
217 }
218
219 if (!test_format(verbose, fp, format_desc, test)) {
220 success = FALSE;
221 }
222 }
223 }
224
225 return success;
226 }
227
228
229 boolean
230 test_all(unsigned verbose, FILE *fp)
231 {
232 enum pipe_format format;
233 boolean success = TRUE;
234
235 util_format_s3tc_init();
236
237 for (format = 1; format < PIPE_FORMAT_COUNT; ++format) {
238 const struct util_format_description *format_desc;
239
240 format_desc = util_format_description(format);
241 if (!format_desc) {
242 continue;
243 }
244
245 /*
246 * TODO: test more
247 */
248
249 if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
250 continue;
251 }
252
253 if (format_desc->layout == UTIL_FORMAT_LAYOUT_S3TC &&
254 !util_format_s3tc_enabled) {
255 continue;
256 }
257
258 if (!test_one(verbose, fp, format_desc)) {
259 success = FALSE;
260 }
261 }
262
263 return success;
264 }
265
266
267 boolean
268 test_some(unsigned verbose, FILE *fp, unsigned long n)
269 {
270 return test_all(verbose, fp);
271 }