1 /**************************************************************************
3 * Copyright 2009 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
31 * Unit tests for blend LLVM IR generation
33 * @author Jose Fonseca <jfonseca@vmware.com>
35 * Blend computation code derived from code written by
36 * @author Brian Paul <brian@vmware.com>
40 #include "lp_bld_type.h"
41 #include "lp_bld_arit.h"
42 #include "lp_bld_blend.h"
43 #include "lp_bld_debug.h"
54 typedef void (*blend_test_ptr_t
)(const void *src
, const void *dst
, const void *con
, void *res
);
58 write_tsv_header(FILE *fp
)
62 "cycles_per_channel\t"
73 "alpha_dst_factor\n");
80 write_tsv_row(FILE *fp
,
81 const struct pipe_blend_state
*blend
,
82 enum vector_mode mode
,
87 fprintf(fp
, "%s\t", success
? "pass" : "fail");
90 fprintf(fp
, "%.1f\t", cycles
/ type
.length
);
95 fprintf(fp
, "%.1f\t", cycles
/ (4 * type
.length
));
99 fprintf(fp
, "%s%u%sx%u\t",
100 type
.floating
? "f" : (type
.fixed
? "h" : (type
.sign
? "s" : "u")),
102 type
.norm
? "n" : "",
107 blend
->rgb_func
!= blend
->alpha_func
? "true" : "false",
108 blend
->rgb_src_factor
!= blend
->alpha_src_factor
? "true" : "false",
109 blend
->rgb_dst_factor
!= blend
->alpha_dst_factor
? "true" : "false");
112 "%s\t%s\t%s\t%s\t%s\t%s\n",
113 debug_dump_blend_func(blend
->rgb_func
, TRUE
),
114 debug_dump_blend_factor(blend
->rgb_src_factor
, TRUE
),
115 debug_dump_blend_factor(blend
->rgb_dst_factor
, TRUE
),
116 debug_dump_blend_func(blend
->alpha_func
, TRUE
),
117 debug_dump_blend_factor(blend
->alpha_src_factor
, TRUE
),
118 debug_dump_blend_factor(blend
->alpha_dst_factor
, TRUE
));
125 dump_blend_type(FILE *fp
,
126 const struct pipe_blend_state
*blend
,
127 enum vector_mode mode
,
130 fprintf(fp
, "%s", mode
? "soa" : "aos");
132 fprintf(fp
, " type=%s%u%sx%u",
133 type
.floating
? "f" : (type
.fixed
? "h" : (type
.sign
? "s" : "u")),
135 type
.norm
? "n" : "",
139 " %s=%s %s=%s %s=%s %s=%s %s=%s %s=%s",
140 "rgb_func", debug_dump_blend_func(blend
->rgb_func
, TRUE
),
141 "rgb_src_factor", debug_dump_blend_factor(blend
->rgb_src_factor
, TRUE
),
142 "rgb_dst_factor", debug_dump_blend_factor(blend
->rgb_dst_factor
, TRUE
),
143 "alpha_func", debug_dump_blend_func(blend
->alpha_func
, TRUE
),
144 "alpha_src_factor", debug_dump_blend_factor(blend
->alpha_src_factor
, TRUE
),
145 "alpha_dst_factor", debug_dump_blend_factor(blend
->alpha_dst_factor
, TRUE
));
147 fprintf(fp
, " ...\n");
153 add_blend_test(LLVMModuleRef module
,
154 const struct pipe_blend_state
*blend
,
155 enum vector_mode mode
,
158 LLVMTypeRef ret_type
;
159 LLVMTypeRef vec_type
;
162 LLVMValueRef src_ptr
;
163 LLVMValueRef dst_ptr
;
164 LLVMValueRef const_ptr
;
165 LLVMValueRef res_ptr
;
166 LLVMBasicBlockRef block
;
167 LLVMBuilderRef builder
;
169 ret_type
= LLVMInt64Type();
170 vec_type
= lp_build_vec_type(type
);
172 args
[3] = args
[2] = args
[1] = args
[0] = LLVMPointerType(vec_type
, 0);
173 func
= LLVMAddFunction(module
, "test", LLVMFunctionType(LLVMVoidType(), args
, 4, 0));
174 LLVMSetFunctionCallConv(func
, LLVMCCallConv
);
175 src_ptr
= LLVMGetParam(func
, 0);
176 dst_ptr
= LLVMGetParam(func
, 1);
177 const_ptr
= LLVMGetParam(func
, 2);
178 res_ptr
= LLVMGetParam(func
, 3);
180 block
= LLVMAppendBasicBlock(func
, "entry");
181 builder
= LLVMCreateBuilder();
182 LLVMPositionBuilderAtEnd(builder
, block
);
190 src
= LLVMBuildLoad(builder
, src_ptr
, "src");
191 dst
= LLVMBuildLoad(builder
, dst_ptr
, "dst");
192 con
= LLVMBuildLoad(builder
, const_ptr
, "const");
194 res
= lp_build_blend_aos(builder
, blend
, type
, src
, dst
, con
, 3);
196 lp_build_name(res
, "res");
198 LLVMBuildStore(builder
, res
, res_ptr
);
208 for(i
= 0; i
< 4; ++i
) {
209 LLVMValueRef index
= LLVMConstInt(LLVMInt32Type(), i
, 0);
210 src
[i
] = LLVMBuildLoad(builder
, LLVMBuildGEP(builder
, src_ptr
, &index
, 1, ""), "");
211 dst
[i
] = LLVMBuildLoad(builder
, LLVMBuildGEP(builder
, dst_ptr
, &index
, 1, ""), "");
212 con
[i
] = LLVMBuildLoad(builder
, LLVMBuildGEP(builder
, const_ptr
, &index
, 1, ""), "");
213 lp_build_name(src
[i
], "src.%c", "rgba"[i
]);
214 lp_build_name(con
[i
], "con.%c", "rgba"[i
]);
215 lp_build_name(dst
[i
], "dst.%c", "rgba"[i
]);
218 lp_build_blend_soa(builder
, blend
, type
, src
, dst
, con
, res
);
220 for(i
= 0; i
< 4; ++i
) {
221 LLVMValueRef index
= LLVMConstInt(LLVMInt32Type(), i
, 0);
222 lp_build_name(res
[i
], "res.%c", "rgba"[i
]);
223 LLVMBuildStore(builder
, res
[i
], LLVMBuildGEP(builder
, res_ptr
, &index
, 1, ""));
227 LLVMBuildRetVoid(builder
);;
229 LLVMDisposeBuilder(builder
);
234 /** Add and limit result to ceiling of 1.0 */
235 #define ADD_SAT(R, A, B) \
237 R = (A) + (B); if (R > 1.0f) R = 1.0f; \
240 /** Subtract and limit result to floor of 0.0 */
241 #define SUB_SAT(R, A, B) \
243 R = (A) - (B); if (R < 0.0f) R = 0.0f; \
248 compute_blend_ref_term(unsigned rgb_factor
,
249 unsigned alpha_factor
,
250 const double *factor
,
258 switch (rgb_factor
) {
259 case PIPE_BLENDFACTOR_ONE
:
260 term
[0] = factor
[0]; /* R */
261 term
[1] = factor
[1]; /* G */
262 term
[2] = factor
[2]; /* B */
264 case PIPE_BLENDFACTOR_SRC_COLOR
:
265 term
[0] = factor
[0] * src
[0]; /* R */
266 term
[1] = factor
[1] * src
[1]; /* G */
267 term
[2] = factor
[2] * src
[2]; /* B */
269 case PIPE_BLENDFACTOR_SRC_ALPHA
:
270 term
[0] = factor
[0] * src
[3]; /* R */
271 term
[1] = factor
[1] * src
[3]; /* G */
272 term
[2] = factor
[2] * src
[3]; /* B */
274 case PIPE_BLENDFACTOR_DST_COLOR
:
275 term
[0] = factor
[0] * dst
[0]; /* R */
276 term
[1] = factor
[1] * dst
[1]; /* G */
277 term
[2] = factor
[2] * dst
[2]; /* B */
279 case PIPE_BLENDFACTOR_DST_ALPHA
:
280 term
[0] = factor
[0] * dst
[3]; /* R */
281 term
[1] = factor
[1] * dst
[3]; /* G */
282 term
[2] = factor
[2] * dst
[3]; /* B */
284 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
285 temp
= MIN2(src
[3], 1.0f
- dst
[3]);
286 term
[0] = factor
[0] * temp
; /* R */
287 term
[1] = factor
[1] * temp
; /* G */
288 term
[2] = factor
[2] * temp
; /* B */
290 case PIPE_BLENDFACTOR_CONST_COLOR
:
291 term
[0] = factor
[0] * con
[0]; /* R */
292 term
[1] = factor
[1] * con
[1]; /* G */
293 term
[2] = factor
[2] * con
[2]; /* B */
295 case PIPE_BLENDFACTOR_CONST_ALPHA
:
296 term
[0] = factor
[0] * con
[3]; /* R */
297 term
[1] = factor
[1] * con
[3]; /* G */
298 term
[2] = factor
[2] * con
[3]; /* B */
300 case PIPE_BLENDFACTOR_SRC1_COLOR
:
301 assert(0); /* to do */
303 case PIPE_BLENDFACTOR_SRC1_ALPHA
:
304 assert(0); /* to do */
306 case PIPE_BLENDFACTOR_ZERO
:
307 term
[0] = 0.0f
; /* R */
308 term
[1] = 0.0f
; /* G */
309 term
[2] = 0.0f
; /* B */
311 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
312 term
[0] = factor
[0] * (1.0f
- src
[0]); /* R */
313 term
[1] = factor
[1] * (1.0f
- src
[1]); /* G */
314 term
[2] = factor
[2] * (1.0f
- src
[2]); /* B */
316 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
317 term
[0] = factor
[0] * (1.0f
- src
[3]); /* R */
318 term
[1] = factor
[1] * (1.0f
- src
[3]); /* G */
319 term
[2] = factor
[2] * (1.0f
- src
[3]); /* B */
321 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
322 term
[0] = factor
[0] * (1.0f
- dst
[3]); /* R */
323 term
[1] = factor
[1] * (1.0f
- dst
[3]); /* G */
324 term
[2] = factor
[2] * (1.0f
- dst
[3]); /* B */
326 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
327 term
[0] = factor
[0] * (1.0f
- dst
[0]); /* R */
328 term
[1] = factor
[1] * (1.0f
- dst
[1]); /* G */
329 term
[2] = factor
[2] * (1.0f
- dst
[2]); /* B */
331 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
332 term
[0] = factor
[0] * (1.0f
- con
[0]); /* R */
333 term
[1] = factor
[1] * (1.0f
- con
[1]); /* G */
334 term
[2] = factor
[2] * (1.0f
- con
[2]); /* B */
336 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
337 term
[0] = factor
[0] * (1.0f
- con
[3]); /* R */
338 term
[1] = factor
[1] * (1.0f
- con
[3]); /* G */
339 term
[2] = factor
[2] * (1.0f
- con
[3]); /* B */
341 case PIPE_BLENDFACTOR_INV_SRC1_COLOR
:
342 assert(0); /* to do */
344 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA
:
345 assert(0); /* to do */
352 * Compute src/first term A
354 switch (alpha_factor
) {
355 case PIPE_BLENDFACTOR_ONE
:
356 term
[3] = factor
[3]; /* A */
358 case PIPE_BLENDFACTOR_SRC_COLOR
:
359 case PIPE_BLENDFACTOR_SRC_ALPHA
:
360 term
[3] = factor
[3] * src
[3]; /* A */
362 case PIPE_BLENDFACTOR_DST_COLOR
:
363 case PIPE_BLENDFACTOR_DST_ALPHA
:
364 term
[3] = factor
[3] * dst
[3]; /* A */
366 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
367 term
[3] = src
[3]; /* A */
369 case PIPE_BLENDFACTOR_CONST_COLOR
:
370 case PIPE_BLENDFACTOR_CONST_ALPHA
:
371 term
[3] = factor
[3] * con
[3]; /* A */
373 case PIPE_BLENDFACTOR_ZERO
:
374 term
[3] = 0.0f
; /* A */
376 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
377 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
378 term
[3] = factor
[3] * (1.0f
- src
[3]); /* A */
380 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
381 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
382 term
[3] = factor
[3] * (1.0f
- dst
[3]); /* A */
384 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
385 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
386 term
[3] = factor
[3] * (1.0f
- con
[3]);
395 compute_blend_ref(const struct pipe_blend_state
*blend
,
404 compute_blend_ref_term(blend
->rgb_src_factor
, blend
->alpha_src_factor
, src
, src
, dst
, con
, src_term
);
405 compute_blend_ref_term(blend
->rgb_dst_factor
, blend
->alpha_dst_factor
, dst
, src
, dst
, con
, dst_term
);
410 switch (blend
->rgb_func
) {
412 ADD_SAT(res
[0], src_term
[0], dst_term
[0]); /* R */
413 ADD_SAT(res
[1], src_term
[1], dst_term
[1]); /* G */
414 ADD_SAT(res
[2], src_term
[2], dst_term
[2]); /* B */
416 case PIPE_BLEND_SUBTRACT
:
417 SUB_SAT(res
[0], src_term
[0], dst_term
[0]); /* R */
418 SUB_SAT(res
[1], src_term
[1], dst_term
[1]); /* G */
419 SUB_SAT(res
[2], src_term
[2], dst_term
[2]); /* B */
421 case PIPE_BLEND_REVERSE_SUBTRACT
:
422 SUB_SAT(res
[0], dst_term
[0], src_term
[0]); /* R */
423 SUB_SAT(res
[1], dst_term
[1], src_term
[1]); /* G */
424 SUB_SAT(res
[2], dst_term
[2], src_term
[2]); /* B */
427 res
[0] = MIN2(src_term
[0], dst_term
[0]); /* R */
428 res
[1] = MIN2(src_term
[1], dst_term
[1]); /* G */
429 res
[2] = MIN2(src_term
[2], dst_term
[2]); /* B */
432 res
[0] = MAX2(src_term
[0], dst_term
[0]); /* R */
433 res
[1] = MAX2(src_term
[1], dst_term
[1]); /* G */
434 res
[2] = MAX2(src_term
[2], dst_term
[2]); /* B */
443 switch (blend
->alpha_func
) {
445 ADD_SAT(res
[3], src_term
[3], dst_term
[3]); /* A */
447 case PIPE_BLEND_SUBTRACT
:
448 SUB_SAT(res
[3], src_term
[3], dst_term
[3]); /* A */
450 case PIPE_BLEND_REVERSE_SUBTRACT
:
451 SUB_SAT(res
[3], dst_term
[3], src_term
[3]); /* A */
454 res
[3] = MIN2(src_term
[3], dst_term
[3]); /* A */
457 res
[3] = MAX2(src_term
[3], dst_term
[3]); /* A */
466 test_one(unsigned verbose
,
468 const struct pipe_blend_state
*blend
,
469 enum vector_mode mode
,
472 LLVMModuleRef module
= NULL
;
473 LLVMValueRef func
= NULL
;
474 LLVMExecutionEngineRef engine
= NULL
;
475 LLVMModuleProviderRef provider
= NULL
;
476 LLVMPassManagerRef pass
= NULL
;
478 blend_test_ptr_t blend_test_ptr
;
480 const unsigned n
= 32;
482 double cycles_avg
= 0.0;
486 dump_blend_type(stdout
, blend
, mode
, type
);
488 module
= LLVMModuleCreateWithName("test");
490 func
= add_blend_test(module
, blend
, mode
, type
);
492 if(LLVMVerifyModule(module
, LLVMPrintMessageAction
, &error
)) {
493 LLVMDumpModule(module
);
496 LLVMDisposeMessage(error
);
498 provider
= LLVMCreateModuleProviderForExistingModule(module
);
499 if (LLVMCreateJITCompiler(&engine
, provider
, 1, &error
)) {
501 dump_blend_type(stderr
, blend
, mode
, type
);
502 fprintf(stderr
, "%s\n", error
);
503 LLVMDisposeMessage(error
);
508 pass
= LLVMCreatePassManager();
509 LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine
), pass
);
510 /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
511 * but there are more on SVN. */
512 LLVMAddConstantPropagationPass(pass
);
513 LLVMAddInstructionCombiningPass(pass
);
514 LLVMAddPromoteMemoryToRegisterPass(pass
);
515 LLVMAddGVNPass(pass
);
516 LLVMAddCFGSimplificationPass(pass
);
517 LLVMRunPassManager(pass
, module
);
523 LLVMDumpModule(module
);
525 blend_test_ptr
= (blend_test_ptr_t
)LLVMGetPointerToGlobal(engine
, func
);
528 lp_disassemble(blend_test_ptr
);
531 for(i
= 0; i
< n
&& success
; ++i
) {
533 uint8_t src
[LP_MAX_VECTOR_LENGTH
*LP_MAX_TYPE_WIDTH
/8];
534 uint8_t dst
[LP_MAX_VECTOR_LENGTH
*LP_MAX_TYPE_WIDTH
/8];
535 uint8_t con
[LP_MAX_VECTOR_LENGTH
*LP_MAX_TYPE_WIDTH
/8];
536 uint8_t res
[LP_MAX_VECTOR_LENGTH
*LP_MAX_TYPE_WIDTH
/8];
537 uint8_t ref
[LP_MAX_VECTOR_LENGTH
*LP_MAX_TYPE_WIDTH
/8];
538 int64_t start_counter
= 0;
539 int64_t end_counter
= 0;
541 random_vec(type
, src
);
542 random_vec(type
, dst
);
543 random_vec(type
, con
);
546 double fsrc
[LP_MAX_VECTOR_LENGTH
];
547 double fdst
[LP_MAX_VECTOR_LENGTH
];
548 double fcon
[LP_MAX_VECTOR_LENGTH
];
549 double fref
[LP_MAX_VECTOR_LENGTH
];
551 read_vec(type
, src
, fsrc
);
552 read_vec(type
, dst
, fdst
);
553 read_vec(type
, con
, fcon
);
555 for(j
= 0; j
< type
.length
; j
+= 4)
556 compute_blend_ref(blend
, fsrc
+ j
, fdst
+ j
, fcon
+ j
, fref
+ j
);
558 write_vec(type
, ref
, fref
);
561 start_counter
= rdtsc();
562 blend_test_ptr(src
, dst
, con
, res
);
563 end_counter
= rdtsc();
565 cycles
[i
] = end_counter
- start_counter
;
567 if(!compare_vec(type
, res
, ref
)) {
571 dump_blend_type(stderr
, blend
, mode
, type
);
572 fprintf(stderr
, "MISMATCH\n");
574 fprintf(stderr
, " Src: ");
575 dump_vec(stderr
, type
, src
);
576 fprintf(stderr
, "\n");
578 fprintf(stderr
, " Dst: ");
579 dump_vec(stderr
, type
, dst
);
580 fprintf(stderr
, "\n");
582 fprintf(stderr
, " Con: ");
583 dump_vec(stderr
, type
, con
);
584 fprintf(stderr
, "\n");
586 fprintf(stderr
, " Res: ");
587 dump_vec(stderr
, type
, res
);
588 fprintf(stderr
, "\n");
590 fprintf(stderr
, " Ref: ");
591 dump_vec(stderr
, type
, ref
);
592 fprintf(stderr
, "\n");
597 const unsigned stride
= type
.length
*type
.width
/8;
598 uint8_t src
[4*LP_MAX_VECTOR_LENGTH
*LP_MAX_TYPE_WIDTH
/8];
599 uint8_t dst
[4*LP_MAX_VECTOR_LENGTH
*LP_MAX_TYPE_WIDTH
/8];
600 uint8_t con
[4*LP_MAX_VECTOR_LENGTH
*LP_MAX_TYPE_WIDTH
/8];
601 uint8_t res
[4*LP_MAX_VECTOR_LENGTH
*LP_MAX_TYPE_WIDTH
/8];
602 uint8_t ref
[4*LP_MAX_VECTOR_LENGTH
*LP_MAX_TYPE_WIDTH
/8];
603 int64_t start_counter
= 0;
604 int64_t end_counter
= 0;
607 for(j
= 0; j
< 4; ++j
) {
608 random_vec(type
, src
+ j
*stride
);
609 random_vec(type
, dst
+ j
*stride
);
610 random_vec(type
, con
+ j
*stride
);
620 for(k
= 0; k
< type
.length
; ++k
) {
621 for(j
= 0; j
< 4; ++j
) {
622 fsrc
[j
] = read_elem(type
, src
+ j
*stride
, k
);
623 fdst
[j
] = read_elem(type
, dst
+ j
*stride
, k
);
624 fcon
[j
] = read_elem(type
, con
+ j
*stride
, k
);
627 compute_blend_ref(blend
, fsrc
, fdst
, fcon
, fref
);
629 for(j
= 0; j
< 4; ++j
)
630 write_elem(type
, ref
+ j
*stride
, k
, fref
[j
]);
634 start_counter
= rdtsc();
635 blend_test_ptr(src
, dst
, con
, res
);
636 end_counter
= rdtsc();
638 cycles
[i
] = end_counter
- start_counter
;
641 for (j
= 0; j
< 4; ++j
)
642 if(!compare_vec(type
, res
+ j
*stride
, ref
+ j
*stride
))
649 dump_blend_type(stderr
, blend
, mode
, type
);
650 fprintf(stderr
, "MISMATCH\n");
651 for(j
= 0; j
< 4; ++j
) {
652 char channel
= "RGBA"[j
];
653 fprintf(stderr
, " Src%c: ", channel
);
654 dump_vec(stderr
, type
, src
+ j
*stride
);
655 fprintf(stderr
, "\n");
657 fprintf(stderr
, " Dst%c: ", channel
);
658 dump_vec(stderr
, type
, dst
+ j
*stride
);
659 fprintf(stderr
, "\n");
661 fprintf(stderr
, " Con%c: ", channel
);
662 dump_vec(stderr
, type
, con
+ j
*stride
);
663 fprintf(stderr
, "\n");
665 fprintf(stderr
, " Res%c: ", channel
);
666 dump_vec(stderr
, type
, res
+ j
*stride
);
667 fprintf(stderr
, "\n");
669 fprintf(stderr
, " Ref%c: ", channel
);
670 dump_vec(stderr
, type
, ref
+ j
*stride
);
671 fprintf(stderr
, "\n");
678 * Unfortunately the output of cycle counter is not very reliable as it comes
679 * -- sometimes we get outliers (due IRQs perhaps?) which are
680 * better removed to avoid random or biased data.
683 double sum
= 0.0, sum2
= 0.0;
687 for(i
= 0; i
< n
; ++i
) {
689 sum2
+= cycles
[i
]*cycles
[i
];
693 std
= sqrtf((sum2
- n
*avg
*avg
)/n
);
697 for(i
= 0; i
< n
; ++i
) {
698 if(fabs(cycles
[i
] - avg
) <= 4.0*std
) {
709 write_tsv_row(fp
, blend
, mode
, type
, cycles_avg
, success
);
713 LLVMDumpModule(module
);
714 LLVMWriteBitcodeToFile(module
, "blend.bc");
715 fprintf(stderr
, "blend.bc written\n");
716 fprintf(stderr
, "Invoke as \"llc -o - blend.bc\"\n");
720 LLVMFreeMachineCodeForFunction(engine
, func
);
722 LLVMDisposeExecutionEngine(engine
);
724 LLVMDisposePassManager(pass
);
732 PIPE_BLENDFACTOR_ZERO
,
733 PIPE_BLENDFACTOR_ONE
,
734 PIPE_BLENDFACTOR_SRC_COLOR
,
735 PIPE_BLENDFACTOR_SRC_ALPHA
,
736 PIPE_BLENDFACTOR_DST_COLOR
,
737 PIPE_BLENDFACTOR_DST_ALPHA
,
738 PIPE_BLENDFACTOR_CONST_COLOR
,
739 PIPE_BLENDFACTOR_CONST_ALPHA
,
741 PIPE_BLENDFACTOR_SRC1_COLOR
,
742 PIPE_BLENDFACTOR_SRC1_ALPHA
,
744 PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
,
745 PIPE_BLENDFACTOR_INV_SRC_COLOR
,
746 PIPE_BLENDFACTOR_INV_SRC_ALPHA
,
747 PIPE_BLENDFACTOR_INV_DST_COLOR
,
748 PIPE_BLENDFACTOR_INV_DST_ALPHA
,
749 PIPE_BLENDFACTOR_INV_CONST_COLOR
,
750 PIPE_BLENDFACTOR_INV_CONST_ALPHA
,
752 PIPE_BLENDFACTOR_INV_SRC1_COLOR
,
753 PIPE_BLENDFACTOR_INV_SRC1_ALPHA
,
762 PIPE_BLEND_REVERSE_SUBTRACT
,
768 const struct lp_type blend_types
[] = {
769 /* float, fixed, sign, norm, width, len */
770 { TRUE
, FALSE
, FALSE
, TRUE
, 32, 4 }, /* f32 x 4 */
771 { FALSE
, FALSE
, FALSE
, TRUE
, 8, 16 }, /* u8n x 16 */
775 const unsigned num_funcs
= sizeof(blend_funcs
)/sizeof(blend_funcs
[0]);
776 const unsigned num_factors
= sizeof(blend_factors
)/sizeof(blend_factors
[0]);
777 const unsigned num_types
= sizeof(blend_types
)/sizeof(blend_types
[0]);
781 test_all(unsigned verbose
, FILE *fp
)
783 const unsigned *rgb_func
;
784 const unsigned *rgb_src_factor
;
785 const unsigned *rgb_dst_factor
;
786 const unsigned *alpha_func
;
787 const unsigned *alpha_src_factor
;
788 const unsigned *alpha_dst_factor
;
789 struct pipe_blend_state blend
;
790 enum vector_mode mode
;
791 const struct lp_type
*type
;
794 for(rgb_func
= blend_funcs
; rgb_func
< &blend_funcs
[num_funcs
]; ++rgb_func
) {
795 for(alpha_func
= blend_funcs
; alpha_func
< &blend_funcs
[num_funcs
]; ++alpha_func
) {
796 for(rgb_src_factor
= blend_factors
; rgb_src_factor
< &blend_factors
[num_factors
]; ++rgb_src_factor
) {
797 for(rgb_dst_factor
= blend_factors
; rgb_dst_factor
<= rgb_src_factor
; ++rgb_dst_factor
) {
798 for(alpha_src_factor
= blend_factors
; alpha_src_factor
< &blend_factors
[num_factors
]; ++alpha_src_factor
) {
799 for(alpha_dst_factor
= blend_factors
; alpha_dst_factor
<= alpha_src_factor
; ++alpha_dst_factor
) {
800 for(mode
= 0; mode
< 2; ++mode
) {
801 for(type
= blend_types
; type
< &blend_types
[num_types
]; ++type
) {
803 if(*rgb_dst_factor
== PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
||
804 *alpha_dst_factor
== PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
)
807 memset(&blend
, 0, sizeof blend
);
808 blend
.blend_enable
= 1;
809 blend
.rgb_func
= *rgb_func
;
810 blend
.rgb_src_factor
= *rgb_src_factor
;
811 blend
.rgb_dst_factor
= *rgb_dst_factor
;
812 blend
.alpha_func
= *alpha_func
;
813 blend
.alpha_src_factor
= *alpha_src_factor
;
814 blend
.alpha_dst_factor
= *alpha_dst_factor
;
815 blend
.colormask
= PIPE_MASK_RGBA
;
817 if(!test_one(verbose
, fp
, &blend
, mode
, *type
))
834 test_some(unsigned verbose
, FILE *fp
, unsigned long n
)
836 const unsigned *rgb_func
;
837 const unsigned *rgb_src_factor
;
838 const unsigned *rgb_dst_factor
;
839 const unsigned *alpha_func
;
840 const unsigned *alpha_src_factor
;
841 const unsigned *alpha_dst_factor
;
842 struct pipe_blend_state blend
;
843 enum vector_mode mode
;
844 const struct lp_type
*type
;
848 for(i
= 0; i
< n
; ++i
) {
849 rgb_func
= &blend_funcs
[random() % num_funcs
];
850 alpha_func
= &blend_funcs
[random() % num_funcs
];
851 rgb_src_factor
= &blend_factors
[random() % num_factors
];
852 alpha_src_factor
= &blend_factors
[random() % num_factors
];
855 rgb_dst_factor
= &blend_factors
[random() % num_factors
];
856 } while(*rgb_dst_factor
== PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
);
859 alpha_dst_factor
= &blend_factors
[random() % num_factors
];
860 } while(*alpha_dst_factor
== PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
);
864 type
= &blend_types
[random() % num_types
];
866 memset(&blend
, 0, sizeof blend
);
867 blend
.blend_enable
= 1;
868 blend
.rgb_func
= *rgb_func
;
869 blend
.rgb_src_factor
= *rgb_src_factor
;
870 blend
.rgb_dst_factor
= *rgb_dst_factor
;
871 blend
.alpha_func
= *alpha_func
;
872 blend
.alpha_src_factor
= *alpha_src_factor
;
873 blend
.alpha_dst_factor
= *alpha_dst_factor
;
874 blend
.colormask
= PIPE_MASK_RGBA
;
876 if(!test_one(verbose
, fp
, &blend
, mode
, *type
))