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