2 * Copyright © 2012 Blaž Tomažič <blaz.tomazic@gmail.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 * @file program_tester.c
27 * Parser and runner for building programs and executing kernels.
36 #include "piglit-framework-cl-program.h"
42 * Watch on subexpressions when modifying regexes, because some of them are
43 * used to retrieve the strings matching them!
47 * Section (section can include whitespace):
48 * <whitespace>[<whitespace>section<whitespace>]<whitespace>
50 #define REGEX_SECTION "^[[:space:]]*\\[[[:space:]]*([[:alnum:]_]+[[:alnum:][:space:]_]*[[:alnum:]_]+|[[:alnum:]_]+)[[:space:]]*\\][[:space:]]*$" /* section */
52 * Key-value (value can have whitespace):
53 * <whitespace>key<whitespace>:<whitespace>value<whitespace>
55 #define REGEX_KEY_VALUE "^[[:space:]]*([[:alnum:]_]+)[[:space:]]*" /* key */ \
57 "[[:space:]]*([^[:space:]#]+[^#]*[^[:space:]#]+|[^[:space:]#]+)[[:space:]]*$" /* value */
62 #define REGEX_IGNORE "^[[:space:]]*$"
65 #define REGEX_ARRAY_DELIMITER "[[:space:]]+"
66 #define REGEX_DEFINE_ARRAY(element) "((" element REGEX_ARRAY_DELIMITER ")*" element ")"
67 #define REGEX_NAN "(nan|NAN|NaN)"
68 #define REGEX_PNAN "([+]?" REGEX_NAN ")"
69 #define REGEX_NNAN "([-]" REGEX_NAN ")"
70 #define REGEX_INF "(infinity|INFINITY|Infinity|inf|INF|Inf)"
71 #define REGEX_PINF "([+]?" REGEX_INF ")"
72 #define REGEX_NINF "([-]" REGEX_INF ")"
73 #define REGEX_NULL "(NULL|null)"
74 #define REGEX_BOOL "(0|1|false|true)"
75 #define REGEX_BOOL_TRUE "(1|true)"
76 #define REGEX_BOOL_FALSE "(0|false)"
77 #define REGEX_INT "(([+-]?[[:digit:]]+)|([+-]?0[Xx][[:digit:]abcdefABCDEF]+))"
78 #define REGEX_UINT "(([+]?[[:digit:]]+)|([+]?0[Xx][[:digit:]abcdefABCDEF]+))"
79 #define REGEX_FLOAT_HEX "([+-]?0[Xx][[:digit:]abcdefABCDEF.]+[[:digit:]pP+-]*)"
80 #define REGEX_FLOAT "(([+-]?[[:digit:]]+(\\.[[:digit:]]+)?e*[+-]*[[:digit:]]*)|" \
81 REGEX_FLOAT_HEX "|" REGEX_PNAN "|" REGEX_NNAN "|" REGEX_PINF "|" \
83 #define REGEX_BOOL_ARRAY REGEX_DEFINE_ARRAY(REGEX_BOOL)
84 #define REGEX_INT_ARRAY REGEX_DEFINE_ARRAY(REGEX_INT)
85 #define REGEX_UINT_ARRAY REGEX_DEFINE_ARRAY(REGEX_UINT)
86 #define REGEX_FLOAT_ARRAY REGEX_DEFINE_ARRAY(REGEX_FLOAT)
87 #define REGEX_VALUE "(" REGEX_NULL "|" REGEX_BOOL "|" REGEX_INT "|" \
88 REGEX_UINT "|" REGEX_FLOAT ")"
89 #define REGEX_ARRAY "(" REGEX_NULL "|" REGEX_BOOL_ARRAY "|" \
90 REGEX_INT_ARRAY "|" REGEX_UINT_ARRAY "|" \
92 #define REGEX_ARRAY_VALUE "(" REGEX_BOOL "|" REGEX_INT "|" REGEX_UINT "|" \
94 #define REGEX_RANDOM "(RANDOM|random)"
95 #define REGEX_REPEAT "(REPEAT|repeat)[[:space:]]+" \
96 REGEX_DEFINE_ARRAY(REGEX_ARRAY_VALUE)
99 #define REGEX_DEFINE_TYPE(type) type"|"type"2|"type"3|"type"4|"type"8|"type"16"
100 #define REGEX_TYPE_CHAR REGEX_DEFINE_TYPE("char")
101 #define REGEX_TYPE_UCHAR REGEX_DEFINE_TYPE("uchar")
102 #define REGEX_TYPE_SHORT REGEX_DEFINE_TYPE("short")
103 #define REGEX_TYPE_USHORT REGEX_DEFINE_TYPE("ushort")
104 #define REGEX_TYPE_INT REGEX_DEFINE_TYPE("int")
105 #define REGEX_TYPE_UINT REGEX_DEFINE_TYPE("uint")
106 #define REGEX_TYPE_LONG REGEX_DEFINE_TYPE("long")
107 #define REGEX_TYPE_ULONG REGEX_DEFINE_TYPE("ulong")
108 // half is defined as unsigned short and C can't read/write its value.
109 // Also half is only used as a storage format unless device supports
111 // TODO: probably we could use libmpdec to handle this
112 // http://www.bytereef.org/mpdecimal/index.html
113 //#define REGEX_TYPE_HALF "buffer half[1]"
114 #define REGEX_TYPE_HALF REGEX_DEFINE_TYPE("half")
115 #define REGEX_TYPE_FLOAT REGEX_DEFINE_TYPE("float")
116 #define REGEX_TYPE_DOUBLE REGEX_DEFINE_TYPE("double")
117 #define REGEX_TYPE REGEX_TYPE_CHAR "|" REGEX_TYPE_UCHAR "|" \
118 REGEX_TYPE_SHORT "|" REGEX_TYPE_USHORT "|" \
119 REGEX_TYPE_INT "|" REGEX_TYPE_UINT "|" \
120 REGEX_TYPE_LONG "|" REGEX_TYPE_ULONG "|" \
121 REGEX_TYPE_HALF "|" REGEX_TYPE_FLOAT "|" REGEX_TYPE_DOUBLE
124 /* TODO: add OpenCL 1.2+ types */
125 #define REGEX_IMGT_2D "2D|2d"
126 #define REGEX_IMGT_3D "3D|3d"
127 #define REGEX_IMAGE_TYPE REGEX_IMGT_2D "|" REGEX_IMGT_3D
130 /* TODO: add OpenCL 2.0 formats */
131 #define REGEX_CHO_R "R|r"
132 #define REGEX_CHO_RX "RX|Rx|rx"
133 #define REGEX_CHO_A "A|a"
134 #define REGEX_CHO_INTENSITY "INTENSITY|intensity"
135 #define REGEX_CHO_LUMINANCE "LUMINANCE|luminance"
136 #define REGEX_CHO_RG "RG|rg"
137 #define REGEX_CHO_RGX "RGX|RGx|rgx"
138 #define REGEX_CHO_RA "RA|ra"
139 #define REGEX_CHO_RGB "RGB|rgb"
140 #define REGEX_CHO_RGBX "RGBX|rgbx"
141 #define REGEX_CHO_RGBA "RGBA|rgba"
142 #define REGEX_CHO_ARGB "ARGB|argb"
143 #define REGEX_CHO_BGRA "BGRA|bgra"
144 #define REGEX_CHANNEL_ORDER REGEX_CHO_R "|" REGEX_CHO_RX "|" REGEX_CHO_A "|" \
145 REGEX_CHO_INTENSITY "|" REGEX_CHO_LUMINANCE "|" \
146 REGEX_CHO_RG "|" REGEX_CHO_RGX "|" \
147 REGEX_CHO_RA "|" REGEX_CHO_RGB "|" \
148 REGEX_CHO_RGBX "|" REGEX_CHO_RGBA "|" \
149 REGEX_CHO_ARGB "|" REGEX_CHO_BGRA
151 #define REGEX_CHT_SNORM_INT8 "SNORM_INT8|snorm_int8"
152 #define REGEX_CHT_SNORM_INT16 "SNORM_INT16|snorm_int16"
153 #define REGEX_CHT_UNORM_INT8 "UNORM_INT8|unorm_int8"
154 #define REGEX_CHT_UNORM_INT16 "UNORM_INT16|unorm_int16"
155 #define REGEX_CHT_UNORM_SHORT_565 "UNORM_SHORT_565|unorm_short_565"
156 #define REGEX_CHT_UNORM_SHORT_555 "UNORM_SHORT_555|unorm_short_555"
157 #define REGEX_CHT_UNORM_INT_101010 "UNORM_INT_101010|unorm_int_101010"
158 #define REGEX_CHT_SIGNED_INT8 "SIGNED_INT8|signed_int8"
159 #define REGEX_CHT_SIGNED_INT16 "SIGNED_INT16|signed_int16"
160 #define REGEX_CHT_SIGNED_INT32 "SIGNED_INT32|signed_int32"
161 #define REGEX_CHT_UNSIGNED_INT8 "UNSIGNED_INT8|unsigned_int8"
162 #define REGEX_CHT_UNSIGNED_INT16 "UNSIGNED_INT16|unsigned_int16"
163 #define REGEX_CHT_UNSIGNED_INT32 "UNSIGNED_INT32|unsigned_int32"
164 #define REGEX_CHT_HALF_FLOAT "HALF_FLOAT|half_float"
165 #define REGEX_CHT_FLOAT "FLOAT|float"
166 #define REGEX_CHANNEL_DATA_TYPE REGEX_CHT_SNORM_INT8 "|" \
167 REGEX_CHT_SNORM_INT16 "|" \
168 REGEX_CHT_UNORM_INT8 "|" \
169 REGEX_CHT_UNORM_INT16 "|" \
170 REGEX_CHT_UNORM_SHORT_565 "|" \
171 REGEX_CHT_UNORM_SHORT_555 "|" \
172 REGEX_CHT_UNORM_INT_101010 "|" \
173 REGEX_CHT_SIGNED_INT8 "|" \
174 REGEX_CHT_SIGNED_INT16 "|" \
175 REGEX_CHT_SIGNED_INT32 "|" \
176 REGEX_CHT_UNSIGNED_INT8 "|" \
177 REGEX_CHT_UNSIGNED_INT16 "|" \
178 REGEX_CHT_UNSIGNED_INT32 "|" \
179 REGEX_CHT_HALF_FLOAT "|" \
183 #define REGEX_SAMP_ADDR_NONE "NONE|none"
184 #define REGEX_SAMP_ADDR_CLAMP_TO_EDGE "CLAMP_TO_EDGE|clamp_to_edge"
185 #define REGEX_SAMP_ADDR_CLAMP "CLAMP|clamp"
186 #define REGEX_SAMP_ADDR_REPEAT "REPEAT|repeat"
187 #define REGEX_SAMP_ADDR_MIRRORED_REPEAT "MIRRORED_REPEAT|mirrored_repeat"
188 #define REGEX_SAMPLER_ADDRESSING_MODE REGEX_SAMP_ADDR_NONE "|"\
189 REGEX_SAMP_ADDR_CLAMP_TO_EDGE "|" \
190 REGEX_SAMP_ADDR_CLAMP "|" \
191 REGEX_SAMP_ADDR_REPEAT "|" \
192 REGEX_SAMP_ADDR_MIRRORED_REPEAT
194 #define REGEX_SAMP_FILT_NEAREST "NEAREST|nearest"
195 #define REGEX_SAMP_FILT_LINEAR "LINEAR|linear"
196 #define REGEX_SAMPLER_FILTER_MODE REGEX_SAMP_FILT_NEAREST "|" \
197 REGEX_SAMP_FILT_LINEAR
201 * index<whitespace>type<whitespace>value
203 * index<whitespace>buffer<whitespace>type[size]<whitespace>(value|random|repeat value)<whitespace>tolerance<whitespace>value
205 * index<whitespace>image<whitespace>type<whitespace>
206 * (value|random|repeat value)<whitespace>
207 * image_type<whitespace>(2d|3d)<whitespace>i
208 * image_width<whitespace>value<whitespace>
209 * image_height<whitespace>value<whitespace>
210 * image_channel_order<whitespace>value<whitespace>
211 * image_channel_data_type<whitespace>value<whitespace>
212 * tolerance<whitespace>value
214 * index<whitespace>sampler<whitespace>
215 * normalized_coords<whitespace>bool<whitespace>
216 * addressing_mode<whitespace>(none|clamp_to_edge|repeat|mirrored_repeat)<whitespace>
217 * filter_mode<whitespace>(nearest|linear)<whitespace>
219 #define REGEX_DEFINE_ARG(type, value) "([[:digit:]]+)[[:space:]]+" type \
220 "[[:space:]]+(" value ")"
221 #define REGEX_ARG_TOLERANCE "tolerance[[:space:]]+(" REGEX_VALUE ")"
222 #define REGEX_ARG_TOLERANCE_ULP REGEX_ARG_TOLERANCE "[[:space:]]+ulp"
223 #define REGEX_ARG_IMAGE_TYPE "image_type[[:space:]]+(" REGEX_IMAGE_TYPE ")"
224 #define REGEX_ARG_IMAGE_WIDTH "image_width[[:space:]]+(" REGEX_UINT ")"
225 #define REGEX_ARG_IMAGE_HEIGHT "image_height[[:space:]]+(" REGEX_UINT ")"
226 #define REGEX_ARG_IMAGE_CHANNEL_ORDER "image_channel_order[[:space:]]+(" REGEX_CHANNEL_ORDER ")"
227 #define REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE "image_channel_data_type[[:space:]]+(" REGEX_CHANNEL_DATA_TYPE ")"
228 #define REGEX_ARG_SAMPLER_NORMALIZED_COORDS "normalized_coords[[:space:]]+" REGEX_BOOL
229 #define REGEX_ARG_SAMPLER_ADDERSSING_MODE "addressing_mode[[:space:]]+(" REGEX_SAMPLER_ADDRESSING_MODE ")"
230 #define REGEX_ARG_SAMPLER_FILTER_MODE "filter_mode[[:space:]]+(" REGEX_SAMPLER_FILTER_MODE ")"
231 #define REGEX_ARG_VALUE REGEX_DEFINE_ARG( "(" REGEX_TYPE ")", REGEX_ARRAY )
232 #define REGEX_ARG_BUFFER REGEX_DEFINE_ARG( "buffer[[:space:]]+(" REGEX_TYPE ")\\[([[:digit:]]+)\\]", \
233 REGEX_ARRAY "|" REGEX_RANDOM "|" REGEX_REPEAT ) \
234 "([[:space:]]+" "("REGEX_ARG_TOLERANCE "|" REGEX_ARG_TOLERANCE_ULP")" ")?"
235 #define REGEX_ARG_IMAGE REGEX_DEFINE_ARG( "image[[:space:]]+(" REGEX_TYPE ")", \
236 REGEX_ARRAY "|" REGEX_RANDOM "|" REGEX_REPEAT ) \
237 "[[:space:]]+"REGEX_ARG_IMAGE_TYPE \
238 "[[:space:]]+"REGEX_ARG_IMAGE_WIDTH \
239 "[[:space:]]+"REGEX_ARG_IMAGE_HEIGHT \
240 "[[:space:]]+"REGEX_ARG_IMAGE_CHANNEL_ORDER \
241 "[[:space:]]+"REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE \
242 "([[:space:]]+" "("REGEX_ARG_TOLERANCE "|" REGEX_ARG_TOLERANCE_ULP")" ")?"
243 #define REGEX_ARG_SAMPLER "([[:digit:]]+)[[:space:]]+sampler" \
244 "[[:space:]]+"REGEX_ARG_SAMPLER_NORMALIZED_COORDS \
245 "[[:space:]]+"REGEX_ARG_SAMPLER_ADDERSSING_MODE \
246 "[[:space:]]+"REGEX_ARG_SAMPLER_FILTER_MODE
247 #define REGEX_ARG "(" REGEX_ARG_VALUE "|" REGEX_ARG_BUFFER "|" \
248 REGEX_ARG_IMAGE "|" REGEX_ARG_SAMPLER ")"
250 /* Match whole line */
251 #define REGEX_FULL_MATCH(content) "^"content"$"
254 #define REGEX_COMMENT_CONFIG "/\\*!(.*)!\\*/"
257 #define REGEX_LINE "^([^#]*)(#.*)?$"
258 #define REGEX_MULTILINE "^([^#]*)\\\\[[:space:]]*$"
260 /* Config function */
261 void init(const int argc
,
263 struct piglit_cl_program_test_config
* config
);
264 void clean(const int argc
,
266 const struct piglit_cl_program_test_config
* config
);
269 /* Kernel test configuration */
272 PIGLIT_CL_PROGRAM_TEST_CONFIG_BEGIN
274 config
.init_func
= (piglit_cl_test_init_t
*)init
;
275 config
.clean_func
= (piglit_cl_test_clean_t
*)clean
;
277 PIGLIT_CL_PROGRAM_TEST_CONFIG_END
279 // Additional options
280 bool expect_test_fail
= false;
281 cl_uint work_dimensions
= 1;
282 size_t global_work_size
[3] = {1, 1, 1};
283 size_t local_work_size
[3] = {1, 1, 1};
284 size_t global_offset
[3] = {0, 0, 0};
285 bool local_work_size_null
= false;
286 bool global_offset_null
= true;
288 /* Helper functions */
291 add_dynamic_array(void** array
,
297 if(((*count
)%GROW_SIZE
) == 0) {
298 void* old_array
= *array
;
300 *array
= malloc(((*count
)/GROW_SIZE
+ 1)*GROW_SIZE
* element_size
);
301 memcpy(*array
, old_array
, (*count
) * element_size
);
306 memcpy((char *)(*array
) + ((*count
)*element_size
), data
, element_size
);
335 enum test_arg_type type
;
337 enum cl_type cl_type
;
338 size_t cl_size
; // 1 for int, 3 for int3
339 size_t cl_mem_size
; // 1 for int, 4 for int3
340 size_t length
; // for buffers
342 /* kernel arg data */
353 piglit_image_desc image_desc
;
354 cl_image_format image_format
;
357 cl_bool sampler_normalized_coords
;
358 cl_addressing_mode sampler_addressing_mode
;
359 cl_filter_mode sampler_filter_mode
;
362 struct test_arg
create_test_arg()
364 struct test_arg ta
= {
365 .type
= TEST_ARG_VALUE
,
367 .cl_type
= TYPE_CHAR
,
388 cl_uint work_dimensions
;
389 size_t global_work_size
[3];
390 size_t local_work_size
[3];
391 bool local_work_size_null
;
392 size_t global_offset
[3];
393 bool global_offset_null
;
395 bool expect_test_fail
;
397 unsigned int num_args_in
;
398 struct test_arg
* args_in
;
400 unsigned int num_args_out
;
401 struct test_arg
* args_out
;
404 unsigned int num_tests
= 0;
405 struct test
* tests
= NULL
;
407 struct test
create_test()
413 .work_dimensions
= work_dimensions
,
414 //.global_work_size = global_work_size,
415 //.local_work_size = local_work_size,
416 .local_work_size_null
= local_work_size_null
,
417 .global_offset_null
= global_offset_null
,
419 .expect_test_fail
= expect_test_fail
,
428 memcpy(t
.global_work_size
, global_work_size
, sizeof(global_work_size
));
429 memcpy(t
.local_work_size
, local_work_size
, sizeof(local_work_size
));
430 memcpy(t
.global_offset
, global_offset
, sizeof(global_offset
));
436 add_test(struct test t
)
438 add_dynamic_array((void**)&tests
, &num_tests
, sizeof(struct test
), &t
);
442 add_test_arg(struct test
* t
, struct test_arg ta
, bool arg_in
)
445 struct test_arg
* this_args
;
446 size_t num_this_args
;
447 struct test_arg
* other_args
;
448 size_t num_other_args
;
451 this_args
= t
->args_in
;
452 num_this_args
= t
->num_args_in
;
453 other_args
= t
->args_out
;
454 num_other_args
= t
->num_args_out
;
456 this_args
= t
->args_out
;
457 num_this_args
= t
->num_args_out
;
458 other_args
= t
->args_in
;
459 num_other_args
= t
->num_args_in
;
462 // Check that argument is new
463 for(i
= 0; i
< num_this_args
; i
++) {
464 struct test_arg ta_this
= this_args
[i
];
466 if(ta
.index
== ta_this
.index
) {
468 "Invalid configuration, %s argument with index %d is already defined\n",
469 arg_in
? "In" : "Out",
474 // Check that types correspond
475 for(i
= 0; i
< num_other_args
; i
++) {
476 struct test_arg ta_other
= other_args
[i
];
478 if(ta
.index
== ta_other
.index
) {
479 if(ta
.type
!= ta_other
.type
) {
481 "Invalid configuration, in argument at index %d isn't compatible with out argument\n",
485 if(ta
.size
!= ta_other
.size
) {
487 "Invalid configuration, Size of in argument (%zu) at index %d isn't the same as size of out argument (%zu)\n",
488 arg_in
? ta
.size
: ta_other
.size
,
490 arg_in
? ta_other
.size
: ta
.size
);
497 add_dynamic_array((void**)&t
->args_in
,
499 sizeof(struct test_arg
),
502 add_dynamic_array((void**)&t
->args_out
,
504 sizeof(struct test_arg
),
512 add_test_arg_in(struct test
* t
, struct test_arg ta
)
514 return add_test_arg(t
, ta
, true);
518 add_test_arg_out(struct test
* t
, struct test_arg ta
)
520 return add_test_arg(t
, ta
, false);
528 for(i
= 0; i
< num_tests
; i
++) {
529 for(j
= 0; j
< tests
[i
].num_args_in
; j
++) {
530 free(tests
[i
].args_in
[j
].value
);
532 free(tests
[i
].args_in
);
533 for(j
= 0; j
< tests
[i
].num_args_out
; j
++) {
534 free(tests
[i
].args_out
[j
].value
);
536 free(tests
[i
].args_out
);
541 unsigned int num_dynamic_strs
= 0;
542 char** dynamic_strs
= NULL
;
545 add_dynamic_str(char* str
)
547 add_dynamic_array((void**)&dynamic_strs
, &num_dynamic_strs
, sizeof(char*), &str
);
551 add_dynamic_str_copy(const char* src
)
553 char* dst
= malloc((strlen(src
)+1) * sizeof(char));
556 add_dynamic_str(dst
);
564 if(dynamic_strs
!= NULL
) {
567 for(i
= 0; i
< num_dynamic_strs
; i
++) {
568 free(dynamic_strs
[i
]);
578 clean(const int argc
,
580 const struct piglit_cl_program_test_config
* config
)
587 exit_report_result(enum piglit_result result
)
591 piglit_report_result(result
);
594 /* Regex functions */
597 regex_get_matches(const char* src
,
607 errcode
= regcomp(&r
, pattern
, REG_EXTENDED
| cflags
);
609 fprintf(stderr
, "Invalid regular expression: '%s'\n", pattern
);
613 /* Match regex and if pmatch != NULL && size > 0 return matched */
614 if(pmatch
== NULL
|| size
== 0) {
615 errcode
= regexec(&r
, src
, 0, NULL
, 0);
617 errcode
= regexec(&r
, src
, size
, pmatch
, 0);
626 regex_get_match_str(char** dst
,
631 size_t size
= pmatch
[index
].rm_eo
- pmatch
[index
].rm_so
;
634 *dst
= malloc((size
+1) * sizeof(char));
635 strncpy(*dst
, src
+pmatch
[index
].rm_so
, size
);
645 regex_get_str(char** dst
,
651 regmatch_t
*pmatch
= calloc(index
+1, sizeof(*pmatch
));
654 if(regex_get_matches(src
, pattern
, pmatch
, index
+1, cflags
)) {
655 ret
= regex_get_match_str(dst
, src
, pmatch
, index
);
663 regex_match(const char* src
, const char* pattern
)
665 return regex_get_matches(src
, pattern
, NULL
, 0, REG_NEWLINE
);
669 regex_section(const char* src
, char** section
)
671 regmatch_t pmatch
[2];
673 if(regex_get_matches(src
, REGEX_SECTION
, pmatch
, 2, REG_NEWLINE
)) {
674 return regex_get_match_str(section
, src
, pmatch
, 1);
681 regex_key_value(const char* src
, char** key
, char** value
)
683 regmatch_t pmatch
[3];
685 if(regex_get_matches(src
, REGEX_KEY_VALUE
, pmatch
, 3, REG_NEWLINE
)) {
688 if( regex_get_match_str(key
, src
, pmatch
, 1)
689 && regex_get_match_str(value
, src
, pmatch
, 2)) {
701 get_bool(const char* src
)
703 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_BOOL_TRUE
))) {
705 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_BOOL_FALSE
))) {
709 "Invalid configuration, could not convert to bool: %s\n",
711 exit_report_result(PIGLIT_WARN
);
717 get_int(const char* src
)
719 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_UINT
))) {
720 return strtoull(src
, NULL
, 0);
721 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_INT
))) {
722 return strtoll(src
, NULL
, 0);
725 "Invalid configuration, could not convert to long: %s\n",
727 exit_report_result(PIGLIT_WARN
);
733 get_uint(const char* src
)
735 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_UINT
))) {
736 return strtoull(src
, NULL
, 0);
739 "Invalid configuration, could not convert to ulong: %s\n",
741 exit_report_result(PIGLIT_WARN
);
747 get_float(const char* src
)
749 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_FLOAT
))) {
750 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_PNAN
))) {
752 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_NNAN
))) {
754 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_PINF
))) {
756 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_NINF
))) {
759 return strtod(src
, NULL
);
763 "Invalid configuration, could not convert to double: %s\n",
765 exit_report_result(PIGLIT_WARN
);
771 get_array_length(const char* src
)
775 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_ARRAY
))) {
776 regmatch_t pmatch
[1];
778 while(regex_get_matches(src
,
779 REGEX_ARRAY_VALUE REGEX_ARRAY_DELIMITER
,
783 src
+= pmatch
[0].rm_eo
;
786 if(regex_match(src
, REGEX_ARRAY_VALUE
)) {
791 "Invalid configuration, could not convert to an array: %s\n",
793 exit_report_result(PIGLIT_WARN
);
800 get_array(const char* src
, void** array
, size_t size
, char* array_pattern
)
808 regmatch_t pmatch
[2];
810 actual_size
= get_array_length(src
);
812 if(!strcmp(array_pattern
, REGEX_BOOL_ARRAY
)) {
814 value_pattern
= REGEX_BOOL REGEX_ARRAY_DELIMITER
;
815 *(bool**)array
= malloc(actual_size
* sizeof(bool));
816 regex_matched
= regex_match(src
, REGEX_FULL_MATCH(REGEX_BOOL_ARRAY
));
817 } else if(!strcmp(array_pattern
, REGEX_INT_ARRAY
)) {
819 value_pattern
= REGEX_INT REGEX_ARRAY_DELIMITER
;
820 *(int64_t**)array
= malloc(actual_size
* sizeof(int64_t));
821 regex_matched
= regex_match(src
, REGEX_FULL_MATCH(REGEX_INT_ARRAY
));
822 } else if(!strcmp(array_pattern
, REGEX_UINT_ARRAY
)) {
824 value_pattern
= REGEX_UINT REGEX_ARRAY_DELIMITER
;
825 *(uint64_t**)array
= malloc(actual_size
* sizeof(uint64_t));
826 regex_matched
= regex_match(src
, REGEX_FULL_MATCH(REGEX_UINT_ARRAY
));
827 } else if(!strcmp(array_pattern
, REGEX_FLOAT_ARRAY
)) {
829 value_pattern
= REGEX_FLOAT REGEX_ARRAY_DELIMITER
;
830 *(double**)array
= malloc(actual_size
* sizeof(double));
831 regex_matched
= regex_match(src
, REGEX_FULL_MATCH(REGEX_FLOAT_ARRAY
));
834 "Internal error, invalid array pattern: %s\n",
836 exit_report_result(PIGLIT_WARN
);
839 if(size
> 0 && actual_size
!= size
) {
841 "Invalid configuration, could not convert %s[%zu] to %s[%zu]: %s\n",
842 type
, actual_size
, type
, size
, src
);
843 exit_report_result(PIGLIT_WARN
);
846 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_NULL
))) {
854 "Invalid configuration, could not convert to %s array: %s\n",
856 exit_report_result(PIGLIT_WARN
);
859 while(regex_get_matches(src
, value_pattern
, pmatch
, 2, 0)) {
860 if(regex_get_match_str(&value
, src
, pmatch
, 1)) {
861 if(!strcmp(array_pattern
, REGEX_BOOL_ARRAY
)) {
862 (*(bool**)array
)[i
] = get_bool(value
);
863 } else if(!strcmp(array_pattern
, REGEX_INT_ARRAY
)) {
864 (*(int64_t**)array
)[i
] = get_int(value
);
865 } else if(!strcmp(array_pattern
, REGEX_UINT_ARRAY
)) {
866 (*(uint64_t**)array
)[i
] = get_uint(value
);
867 } else if(!strcmp(array_pattern
, REGEX_FLOAT_ARRAY
)) {
868 (*(double**)array
)[i
] = get_float(value
);
873 "Invalid configuration, could not read %s on index %zu: %s\n",
875 exit_report_result(PIGLIT_WARN
);
878 src
+= pmatch
[0].rm_eo
;
882 if(!strcmp(array_pattern
, REGEX_BOOL_ARRAY
)) {
883 (*(bool**)array
)[i
] = get_bool(src
);
884 } else if(!strcmp(array_pattern
, REGEX_INT_ARRAY
)) {
885 (*(int64_t**)array
)[i
] = get_int(src
);
886 } else if(!strcmp(array_pattern
, REGEX_UINT_ARRAY
)) {
887 (*(uint64_t**)array
)[i
] = get_uint(src
);
888 } else if(!strcmp(array_pattern
, REGEX_FLOAT_ARRAY
)) {
889 (*(double**)array
)[i
] = get_float(src
);
896 get_bool_array(const char* src
, bool** array
, size_t size
)
898 return get_array(src
, (void**)array
, size
, REGEX_BOOL_ARRAY
);
902 get_int_array(const char* src
, int64_t** array
, size_t size
)
904 return get_array(src
, (void**)array
, size
, REGEX_INT_ARRAY
);
908 get_uint_array(const char* src
, uint64_t** array
, size_t size
)
910 return get_array(src
, (void**)array
, size
, REGEX_UINT_ARRAY
);
914 get_float_array(const char* src
, double** array
, size_t size
)
916 return get_array(src
, (void**)array
, size
, REGEX_FLOAT_ARRAY
);
922 print_usage(const int argc
, const char** argv
)
925 " %s [options] CONFIG.program_test\n"
926 " %s [options] [-config CONFIG.program_test] PROGRAM.cl|PROGRAM.bin\n"
929 " - If CONFIG is not specified and PROGRAM has a comment config then a\n"
930 " comment config is used.\n"
931 " - If there is no CONFIG or comment config, then the program is only\n"
932 " tested to build properly.\n",
937 print_usage_and_warn(const int argc
, const char** argv
, const char* fmt
, ...)
941 fprintf(stderr
, "ERROR: ");
943 vfprintf(stderr
, fmt
, args
);
947 print_usage(argc
, argv
);
949 exit_report_result(PIGLIT_WARN
);
952 /* Parse configuration */
955 get_section_content(const char* src
, char** content
)
958 size_t section_name_length
= strcspn(src
, "\n\0");
959 regmatch_t pmatch
[2];
961 if(src
[section_name_length
] != '\0') {
962 src
+= section_name_length
+1;
964 src
+= section_name_length
;
967 if(regex_get_matches(src
, REGEX_SECTION
, pmatch
, 2, REG_NEWLINE
)) { // found next section
968 size
= pmatch
[1].rm_so
-1;
969 } else { // no next section
973 *content
= malloc((size
+1) * sizeof(char));
974 strncpy(*content
, src
, size
);
975 (*content
)[size
] = '\0';
981 get_test_arg_value(struct test_arg
* test_arg
, const char* value
, size_t length
)
983 size_t i
; // index in array
984 size_t c
; // component in element
985 size_t ra
; // offset from the beginning of array
986 size_t rb
; // offset from the beginning of bufffer
988 int64_t* int_array
= NULL
;
989 uint64_t* uint_array
= NULL
;
990 double* float_array
= NULL
;
992 test_arg
->value
= malloc(test_arg
->size
);
995 * We fill the buffer with calculating the right offsets in the buffer (rb)
996 * and in the array (ra). Buffers of type3 have have stride of
997 * 4*sizeof(type) while array has a stride of 3*sizeof(parsed_type).
998 * Also the array index is inside length parameter modulo, so we can fill
999 * the buffer with repeateable values.
1001 #define CASE(enum_type, cl_type, get_func, array) \
1003 get_func(value, &array, length); \
1004 for(i = 0; i < test_arg->length; i++) { \
1005 for(c = 0; c < test_arg->cl_size; c++) { \
1006 ra = i*test_arg->cl_size + c; \
1007 rb = i*test_arg->cl_mem_size + c; \
1008 ((cl_type*)test_arg->value)[rb] = convert_##cl_type(array[ra%length]); \
1013 switch(test_arg
->cl_type
) {
1014 CASE(TYPE_CHAR
, cl_char
, get_int_array
, int_array
)
1015 CASE(TYPE_UCHAR
, cl_uchar
, get_uint_array
, uint_array
)
1016 CASE(TYPE_SHORT
, cl_short
, get_int_array
, int_array
)
1017 CASE(TYPE_USHORT
, cl_ushort
, get_uint_array
, uint_array
)
1018 CASE(TYPE_INT
, cl_int
, get_int_array
, int_array
)
1019 CASE(TYPE_UINT
, cl_uint
, get_uint_array
, uint_array
)
1020 CASE(TYPE_LONG
, cl_long
, get_int_array
, int_array
)
1021 CASE(TYPE_ULONG
, cl_ulong
, get_uint_array
, uint_array
)
1022 CASE(TYPE_HALF
, cl_half
, get_float_array
, float_array
)
1023 CASE(TYPE_FLOAT
, cl_float
, get_float_array
, float_array
)
1024 CASE(TYPE_DOUBLE
, cl_double
, get_float_array
, float_array
)
1035 get_test_arg_tolerance(struct test_arg
* test_arg
, const char* tolerance_str
)
1037 regmatch_t pmatch
[2];
1038 char* value_str
= NULL
;
1040 if(regex_get_matches(tolerance_str
,
1041 REGEX_ARG_TOLERANCE_ULP
,
1045 regex_get_match_str(&value_str
, tolerance_str
, pmatch
, 1);
1046 switch(test_arg
->cl_type
) {
1050 test_arg
->ulp
= get_uint(value_str
);
1053 fprintf(stderr
, "ulp not value for integer types\n");
1054 exit_report_result(PIGLIT_WARN
);
1058 if(regex_get_matches(tolerance_str
,
1059 REGEX_ARG_TOLERANCE
,
1063 regex_get_match_str(&value_str
, tolerance_str
, pmatch
, 1);
1065 switch(test_arg
->cl_type
) {
1070 test_arg
->toli
= get_int(value_str
);
1076 test_arg
->tolu
= get_uint(value_str
);
1081 float value
= get_float(value_str
);
1082 test_arg
->ulp
= *((uint64_t*)(&value
));
1090 "Invalid configuration, could not parse tolerance: %s\n",
1092 exit_report_result(PIGLIT_WARN
);
1097 get_test_arg(const char* src
, struct test
* test
, bool arg_in
)
1099 regmatch_t pmatch
[5];
1100 char* index_str
= NULL
;
1103 struct test_arg test_arg
= create_test_arg();
1104 bool has_type
= true;
1107 if(regex_get_matches(src
, REGEX_FULL_MATCH(REGEX_ARG_VALUE
),
1108 pmatch
, 5, REG_NEWLINE
)) { // value
1110 } else if(regex_get_matches(src
, REGEX_FULL_MATCH(REGEX_ARG_BUFFER
),
1111 pmatch
, 5, REG_NEWLINE
)) { // buffer
1113 } else if(regex_get_matches(src
, REGEX_FULL_MATCH(REGEX_ARG_IMAGE
),
1114 pmatch
, 5, REG_NEWLINE
)) { // image
1116 } else if(regex_get_matches(src
, REGEX_FULL_MATCH(REGEX_ARG_SAMPLER
),
1117 pmatch
, 5, REG_NEWLINE
)) { // sampler
1121 "Invalid configuration, invalid test argument: %s\n",
1123 exit_report_result(PIGLIT_WARN
);
1127 regex_get_match_str(&index_str
, src
, pmatch
, 1);
1128 test_arg
.index
= get_int(index_str
);
1132 /* Set type, cl_size, cl_mem_size and size (partially for buffers) */
1133 regex_get_match_str(&type
, src
, pmatch
, 2);
1134 if(regex_match(type
, "[[:digit:]]+")) {
1135 char* type_size_str
;
1136 regex_get_str(&type_size_str
, type
, "[[:digit:]]+", 0, REG_NEWLINE
);
1137 test_arg
.cl_size
= get_int(type_size_str
);
1138 test_arg
.cl_mem_size
= test_arg
.cl_size
!= 3 ? test_arg
.cl_size
: 4; // test if we have type3
1139 free(type_size_str
);
1141 test_arg
.cl_size
= 1;
1142 test_arg
.cl_mem_size
= 1;
1145 #define IF(regex_type, enum_type, main_type) \
1146 if(regex_match(type, REGEX_FULL_MATCH(regex_type))) { \
1147 test_arg.cl_type = enum_type; \
1148 test_arg.size = sizeof(main_type) * test_arg.cl_mem_size; \
1150 #define ELSEIF(regex_type, enum_type, main_type) \
1151 else IF(regex_type, enum_type, main_type)
1153 IF (REGEX_TYPE_CHAR
, TYPE_CHAR
, cl_char
)
1154 ELSEIF(REGEX_TYPE_UCHAR
, TYPE_UCHAR
, cl_uchar
)
1155 ELSEIF(REGEX_TYPE_SHORT
, TYPE_SHORT
, cl_short
)
1156 ELSEIF(REGEX_TYPE_USHORT
, TYPE_USHORT
, cl_ushort
)
1157 ELSEIF(REGEX_TYPE_INT
, TYPE_INT
, cl_int
)
1158 ELSEIF(REGEX_TYPE_UINT
, TYPE_UINT
, cl_uint
)
1159 ELSEIF(REGEX_TYPE_LONG
, TYPE_LONG
, cl_long
)
1160 ELSEIF(REGEX_TYPE_ULONG
, TYPE_ULONG
, cl_ulong
)
1161 ELSEIF(REGEX_TYPE_HALF
, TYPE_HALF
, cl_half
)
1162 ELSEIF(REGEX_TYPE_FLOAT
, TYPE_FLOAT
, cl_float
)
1163 ELSEIF(REGEX_TYPE_DOUBLE
, TYPE_DOUBLE
, cl_double
)
1171 /* Get arg type, size and value */
1172 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_ARG_VALUE
))) { // value
1173 /* Values are only allowed for in arguments */
1176 "Invalid configuration, only arg_in values are allowed: %s\n",
1178 exit_report_result(PIGLIT_WARN
);
1182 test_arg
.type
= TEST_ARG_VALUE
;
1185 test_arg
.length
= 1;
1188 regex_get_match_str(&value
, src
, pmatch
, 3);
1189 if(regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1190 test_arg
.value
= NULL
;
1192 get_test_arg_value(&test_arg
, value
, test_arg
.cl_size
);
1195 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_ARG_BUFFER
))) { // buffer
1196 char* array_length_str
= NULL
;
1197 const char* tolerance_str
= NULL
;
1200 test_arg
.type
= TEST_ARG_BUFFER
;
1203 regex_get_match_str(&array_length_str
, src
, pmatch
, 3);
1204 test_arg
.length
= get_int(array_length_str
);
1205 free(array_length_str
);
1208 test_arg
.size
= test_arg
.size
* test_arg
.length
;
1211 tolerance_str
= src
+pmatch
[4].rm_eo
;
1212 if(regex_match(tolerance_str
, REGEX_ARG_TOLERANCE
)) {
1215 "Invalid configuration, in argument buffer can't have tolerance: %s\n",
1217 exit_report_result(PIGLIT_WARN
);
1219 get_test_arg_tolerance(&test_arg
, tolerance_str
);
1223 regex_get_match_str(&value
, src
, pmatch
, 4);
1224 if(regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1225 test_arg
.value
= NULL
;
1228 "Invalid configuration, out argument buffer value can not be NULL: %s\n",
1230 exit_report_result(PIGLIT_WARN
);
1233 if(regex_match(value
, REGEX_FULL_MATCH(REGEX_RANDOM
))) {
1234 test_arg
.value
= malloc(test_arg
.size
);
1237 "Invalid configuration, out argument buffer can not be random: %s\n",
1239 exit_report_result(PIGLIT_WARN
);
1241 } else if(regex_match(value
, REGEX_FULL_MATCH(REGEX_REPEAT
))) {
1242 regmatch_t rmatch
[3];
1243 char* repeat_value_str
;
1245 regex_get_matches(value
, REGEX_REPEAT
, rmatch
, 3, 0);
1246 regex_get_match_str(&repeat_value_str
, value
, rmatch
, 2);
1248 get_test_arg_value(&test_arg
,
1250 get_array_length(repeat_value_str
));
1252 free(repeat_value_str
);
1253 } else if(regex_match(value
, REGEX_ARRAY
)) {
1254 get_test_arg_value(&test_arg
,
1256 test_arg
.length
* test_arg
.cl_size
);
1260 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_ARG_IMAGE
))) { // image
1262 const char* properties_str
= src
+ pmatch
[3].rm_eo
;
1263 const char* tolerance_str
= NULL
;
1264 size_t image_elems
= 0;
1265 cl_channel_order cho
;
1266 cl_channel_type cht
;
1267 regmatch_t pmatch_prop
[2];
1270 test_arg
.type
= TEST_ARG_IMAGE
;
1273 regex_get_matches(properties_str
, REGEX_ARG_IMAGE_TYPE
,
1274 pmatch_prop
, 2, REG_NEWLINE
);
1275 regex_get_match_str(&str
, properties_str
, pmatch_prop
, 1);
1276 properties_str
+= pmatch_prop
[1].rm_eo
;
1277 if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_IMGT_2D
")"))) {
1278 test_arg
.image_desc
.image_type
= CL_MEM_OBJECT_IMAGE2D
;
1280 /* TODO: Implement other image types */
1281 fprintf(stderr
, "Image type not supported: %s\n", str
);
1282 exit_report_result(PIGLIT_WARN
);
1287 regex_get_matches(properties_str
, REGEX_ARG_IMAGE_WIDTH
,
1288 pmatch_prop
, 2, REG_NEWLINE
);
1289 regex_get_match_str(&str
, properties_str
, pmatch_prop
, 1);
1290 properties_str
+= pmatch_prop
[1].rm_eo
;
1291 test_arg
.image_desc
.image_width
= get_int(str
);
1295 regex_get_matches(properties_str
, REGEX_ARG_IMAGE_HEIGHT
,
1296 pmatch_prop
, 2, REG_NEWLINE
);
1297 regex_get_match_str(&str
, properties_str
, pmatch_prop
, 1);
1298 properties_str
+= pmatch_prop
[1].rm_eo
;
1299 test_arg
.image_desc
.image_height
= get_int(str
);
1302 /* Image descriptor defaults */
1303 test_arg
.image_desc
.image_depth
= 1;
1304 test_arg
.image_desc
.image_array_size
= 1;
1305 test_arg
.image_desc
.image_row_pitch
= 0;
1306 test_arg
.image_desc
.image_slice_pitch
= 0;
1307 test_arg
.image_desc
.num_mip_levels
= 0;
1308 test_arg
.image_desc
.num_samples
= 0;
1309 test_arg
.image_desc
.buffer
= NULL
;
1311 /* Image channel order */
1312 regex_get_matches(properties_str
, REGEX_ARG_IMAGE_CHANNEL_ORDER
,
1313 pmatch_prop
, 2, REG_NEWLINE
);
1314 regex_get_match_str(&str
, properties_str
, pmatch_prop
, 1);
1315 properties_str
+= pmatch_prop
[1].rm_eo
;
1316 if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_R
")"))) {
1318 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RX
")"))) {
1320 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_A
")"))) {
1322 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_INTENSITY
")"))) {
1324 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_LUMINANCE
")"))) {
1326 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RG
")"))) {
1328 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RGX
")"))) {
1330 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RA
")"))) {
1332 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RGB
")"))) {
1334 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RGBX
")"))) {
1336 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RGBA
")"))) {
1338 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_ARGB
")"))) {
1340 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_BGRA
")"))) {
1343 fprintf(stderr
, "Image channel order not supported: %s\n", str
);
1344 exit_report_result(PIGLIT_WARN
);
1347 test_arg
.image_format
.image_channel_order
= cho
;
1349 /* Image channel data type */
1350 regex_get_matches(properties_str
, REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE
,
1351 pmatch_prop
, 2, REG_NEWLINE
);
1352 regex_get_match_str(&str
, properties_str
, pmatch_prop
, 1);
1353 properties_str
+= pmatch_prop
[1].rm_eo
;
1354 if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_SNORM_INT8
")"))) {
1355 cht
= CL_SNORM_INT8
;
1356 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_SNORM_INT16
")"))) {
1357 cht
= CL_SNORM_INT16
;
1358 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT8
")"))) {
1359 cht
= CL_UNORM_INT8
;
1360 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT16
")"))) {
1361 cht
= CL_UNORM_INT16
;
1362 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_SHORT_565
")"))) {
1363 cht
= CL_UNORM_SHORT_565
;
1364 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_SHORT_555
")"))) {
1365 cht
= CL_UNORM_SHORT_555
;
1366 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT_101010
")"))) {
1367 cht
= CL_UNORM_INT_101010
;
1368 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT8
")"))) {
1369 cht
= CL_SIGNED_INT8
;
1370 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT16
")"))) {
1371 cht
= CL_SIGNED_INT16
;
1372 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT32
")"))) {
1373 cht
= CL_SIGNED_INT32
;
1374 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT8
")"))) {
1375 cht
= CL_UNSIGNED_INT8
;
1376 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT16
")"))) {
1377 cht
= CL_UNSIGNED_INT16
;
1378 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT32
")"))) {
1379 cht
= CL_UNSIGNED_INT32
;
1380 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_HALF_FLOAT
")"))) {
1381 cht
= CL_HALF_FLOAT
;
1382 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_FLOAT
")"))) {
1385 fprintf(stderr
, "Image channel data type not supported: %s\n", str
);
1386 exit_report_result(PIGLIT_WARN
);
1389 test_arg
.image_format
.image_channel_data_type
= cht
;
1392 image_elems
= test_arg
.image_desc
.image_width
*
1393 test_arg
.image_desc
.image_height
*
1394 test_arg
.image_desc
.image_depth
*
1395 test_arg
.image_desc
.image_array_size
;
1396 test_arg
.length
= image_elems
;
1397 test_arg
.size
*= image_elems
;
1400 tolerance_str
= properties_str
;
1401 if(regex_match(tolerance_str
, REGEX_ARG_TOLERANCE
)) {
1404 "Invalid configuration, in argument buffer can't have tolerance: %s\n",
1406 exit_report_result(PIGLIT_WARN
);
1408 get_test_arg_tolerance(&test_arg
, tolerance_str
);
1412 regex_get_match_str(&value
, src
, pmatch
, 3);
1413 if(regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1414 test_arg
.value
= NULL
;
1417 "Invalid configuration, out argument buffer value can not be NULL: %s\n",
1419 exit_report_result(PIGLIT_WARN
);
1422 if(regex_match(value
, REGEX_FULL_MATCH(REGEX_RANDOM
))) {
1423 test_arg
.value
= malloc(test_arg
.size
);
1426 "Invalid configuration, out argument buffer can not be random: %s\n",
1428 exit_report_result(PIGLIT_WARN
);
1430 } else if(regex_match(value
, REGEX_FULL_MATCH(REGEX_REPEAT
))) {
1431 regmatch_t rmatch
[3];
1432 char* repeat_value_str
;
1434 regex_get_matches(value
, REGEX_REPEAT
, rmatch
, 3, 0);
1435 regex_get_match_str(&repeat_value_str
, value
, rmatch
, 2);
1437 get_test_arg_value(&test_arg
,
1439 get_array_length(repeat_value_str
));
1441 free(repeat_value_str
);
1442 } else if(regex_match(value
, REGEX_ARRAY
)) {
1443 get_test_arg_value(&test_arg
, value
,
1444 image_elems
* test_arg
.cl_size
);
1449 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_ARG_SAMPLER
))) { // sampler
1452 /* Samplers are only allowed for in arguments */
1455 "Invalid configuration, only arg_in samplers are allowed: %s\n",
1457 exit_report_result(PIGLIT_WARN
);
1460 test_arg
.size
= sizeof(cl_sampler
);
1463 test_arg
.type
= TEST_ARG_SAMPLER
;
1465 /* Normalized coords */
1466 regex_get_match_str(&str
, src
, pmatch
, 2);
1467 test_arg
.sampler_normalized_coords
= get_bool(str
);
1470 /* Addressing mode */
1471 regex_get_match_str(&str
, src
, pmatch
, 3);
1472 if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_NONE
")"))) {
1473 test_arg
.sampler_addressing_mode
= CL_ADDRESS_NONE
;
1474 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_CLAMP_TO_EDGE
")"))) {
1475 test_arg
.sampler_addressing_mode
= CL_ADDRESS_CLAMP_TO_EDGE
;
1476 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_CLAMP
")"))) {
1477 test_arg
.sampler_addressing_mode
= CL_ADDRESS_CLAMP
;
1478 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_REPEAT
))) {
1479 test_arg
.sampler_addressing_mode
= CL_ADDRESS_REPEAT
;
1480 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_MIRRORED_REPEAT
))) {
1481 test_arg
.sampler_addressing_mode
= CL_ADDRESS_MIRRORED_REPEAT
;
1483 fprintf(stderr
, "Sampler addressing mode not supported: %s\n", str
);
1484 exit_report_result(PIGLIT_WARN
);
1489 regex_get_match_str(&str
, src
, pmatch
, 4);
1490 if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_FILT_NEAREST
")"))) {
1491 test_arg
.sampler_filter_mode
= CL_FILTER_NEAREST
;
1492 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_FILT_LINEAR
")"))) {
1493 test_arg
.sampler_filter_mode
= CL_FILTER_LINEAR
;
1495 fprintf(stderr
, "Sampler filter mode not supported: %s\n", str
);
1496 exit_report_result(PIGLIT_WARN
);
1502 if(!add_test_arg_in(test
, test_arg
)) {
1504 "Invalid configuration, could not add in argument: %s\n",
1506 exit_report_result(PIGLIT_WARN
);
1509 if(!add_test_arg_out(test
, test_arg
)) {
1511 "Invalid configuration, could not add out argument: %s\n",
1513 exit_report_result(PIGLIT_WARN
);
1519 * Helper function for parsing a test name and checking for illegal characters.
1522 parse_name(const char *input
)
1524 char *name
= add_dynamic_str_copy(input
);
1527 regmatch_t pmatch
[1];
1530 if ((error
= regcomp(®ex
, "\\([/%]\\)",0))) {
1532 regerror(error
, ®ex
, errbuf
, 100);
1533 fprintf(stderr
, "Failed to compile regex for parse_name():%s\n", errbuf
);
1537 if (!regexec(®ex
, input
, 1, pmatch
, 0)) {
1538 char bad_char
= *(input
+ pmatch
[0].rm_so
);
1539 fprintf(stderr
, "Illegal character in test name '%s': %c\n",
1549 parse_config(const char* config_str
,
1550 struct piglit_cl_program_test_config
* config
)
1553 size_t length
= strlen(config_str
);
1556 char* section
= NULL
;
1560 struct test
* test
= NULL
;
1562 bool config_found
= false;
1563 bool test_found
= false;
1569 } state
= SECTION_NONE
;
1571 /* parse config string by each line */
1573 while(pch
< (config_str
+length
)) {
1574 regmatch_t pmatch
[2];
1578 regex_get_matches(pch
, REGEX_LINE
, pmatch
, 2, REG_NEWLINE
);
1579 line_length
= pmatch
[0].rm_eo
- pmatch
[0].rm_so
;
1580 if(!regex_get_match_str(&line
, pch
, pmatch
, 1)) {
1582 pch
+= line_length
+ 1;
1586 /* Get more lines if it is a multiline */
1587 if( regex_match(line
, REGEX_KEY_VALUE
)
1588 && regex_match(line
, REGEX_MULTILINE
)) {
1589 char* multiline
= malloc(sizeof(char));
1590 multiline
[0] = '\0';
1592 free(line
); line
= NULL
;
1594 while((pch
<= (config_str
+length
))) {
1595 regmatch_t mmatch
[2];
1596 char* old_multiline
= multiline
;
1597 char* new_multiline
;
1600 regex_get_matches(pch
, REGEX_LINE
, pmatch
, 2, REG_NEWLINE
);
1601 line_length
= pmatch
[0].rm_eo
- pmatch
[0].rm_so
;
1602 if(!regex_get_match_str(&line
, pch
, pmatch
, 1)) {
1607 if(regex_match(line
, REGEX_MULTILINE
)) { // not last line
1608 regex_get_matches(line
, REGEX_MULTILINE
,
1609 mmatch
, 2, REG_NEWLINE
);
1610 if(!regex_get_match_str(&new_multiline
, pch
, mmatch
, 1)) {
1611 /* Multiline is empty */
1612 pch
+= line_length
+ 1;
1616 multiline
= malloc(strlen(old_multiline
) + strlen(new_multiline
) + 1);
1617 strncpy(multiline
, old_multiline
, strlen(old_multiline
));
1618 strcpy(multiline
+strlen(old_multiline
), new_multiline
);
1620 pch
+= line_length
+1;
1622 free(line
); free(old_multiline
); free(new_multiline
);
1623 } else { // last line
1624 multiline
= malloc(strlen(old_multiline
) + strlen(line
) + 1);
1625 strncpy(multiline
, old_multiline
, strlen(old_multiline
));
1626 strcpy(multiline
+strlen(old_multiline
), line
);
1628 free(line
); free(old_multiline
);
1637 if(regex_section(line
, §ion
)) { // SECTION
1638 if(regex_match(section
, "^config$")) { // config
1640 fprintf(stderr
, "Invalid configuration, [config] section can be defined only once\n");
1641 free(section
); section
= NULL
;
1642 exit_report_result(PIGLIT_WARN
);
1645 fprintf(stderr
, "Invalid configuration, [config] section must be declared before any [test] section\n");
1646 free(section
); section
= NULL
;
1647 exit_report_result(PIGLIT_WARN
);
1649 config_found
= true;
1650 state
= SECTION_CONFIG
;
1651 } else if(regex_match(section
, "^test$")) { // test
1653 fprintf(stderr
, "Invalid configuration, [config] section must be declared before any [test] section\n");
1654 free(section
); section
= NULL
;
1655 exit_report_result(PIGLIT_WARN
);
1657 if(config
->expect_build_fail
) {
1658 fprintf(stderr
, "Invalid configuration, no tests can be defined when expect_build_fail is true\n");
1659 free(section
); section
= NULL
;
1660 exit_report_result(PIGLIT_WARN
);
1663 add_test(create_test());
1664 test
= &tests
[num_tests
-1];
1665 state
= SECTION_TEST
;
1666 } else if(regex_match(section
, "^program source$")) { // program source
1667 pch
+= get_section_content(pch
, &config
->program_source
);
1668 add_dynamic_str(config
->program_source
);
1669 state
= SECTION_NONE
;
1670 } else if(regex_match(section
, "^program binary$")) { // program binary
1671 pch
+= get_section_content(pch
, (char**)&config
->program_binary
);
1672 add_dynamic_str((char*)config
->program_binary
);
1673 state
= SECTION_NONE
;
1676 "Invalid configuration, configuration has an invalid section: [%s]\n",
1678 free(section
); section
= NULL
;
1679 exit_report_result(PIGLIT_WARN
);
1682 free(section
); section
= NULL
;
1683 } else if(regex_key_value(line
, &key
, &value
)) { // KEY : VALUE
1687 "Invalid configuration, this key-value does not belong to any section: %s\n",
1689 free(key
); key
= NULL
;
1690 free(value
); value
= NULL
;
1691 exit_report_result(PIGLIT_WARN
);
1693 case SECTION_CONFIG
:
1694 if(regex_match(key
, "^name$")) {
1695 config
->name
= parse_name(value
);
1696 if (!config
->name
) {
1697 exit_report_result(PIGLIT_FAIL
);
1699 } else if(regex_match(key
, "^clc_version_min$")) {
1700 config
->clc_version_min
= get_int(value
);
1701 } else if(regex_match(key
, "clc_version_max$")) {
1702 config
->clc_version_max
= get_int(value
);
1703 } else if(regex_match(key
, "^platform_regex$")) {
1704 config
->platform_regex
= add_dynamic_str_copy(value
);
1705 } else if(regex_match(key
, "^device_regex$")) {
1706 config
->device_regex
= add_dynamic_str_copy(value
);
1707 } else if(regex_match(key
, "^require_platform_extensions$")) {
1708 config
->require_platform_extensions
=
1709 add_dynamic_str_copy(value
);
1710 } else if(regex_match(key
, "^require_device_extensions$")) {
1711 config
->require_device_extensions
=
1712 add_dynamic_str_copy(value
);
1713 } else if(regex_match(key
, "^program_source_file$")) {
1714 config
->program_source_file
= add_dynamic_str_copy(value
);
1715 } else if(regex_match(key
, "^program_binary_file$")) {
1716 config
->program_binary_file
= add_dynamic_str_copy(value
);
1717 } else if(regex_match(key
, "^build_options$")) {
1718 config
->build_options
= add_dynamic_str_copy(value
);
1719 } else if(regex_match(key
, "^kernel_name$")) {
1720 if(!regex_match(value
, REGEX_NULL
)) {
1721 config
->kernel_name
= add_dynamic_str_copy(value
);
1723 config
->kernel_name
= NULL
;
1725 } else if(regex_match(key
, "^expect_build_fail$")) {
1726 config
->expect_build_fail
= get_bool(value
);
1727 } else if(regex_match(key
, "^expect_test_fail$")) {
1728 expect_test_fail
= get_bool(value
);
1729 } else if(regex_match(key
, "^need_image_support$")) {
1730 config
->need_image_support
= get_bool(value
);
1731 } else if(regex_match(key
, "^dimensions$")) {
1732 work_dimensions
= get_uint(value
);
1733 } else if(regex_match(key
, "^global_size$")) {
1735 uint64_t* int_global_work_size
;
1736 get_uint_array(value
, &int_global_work_size
, 3);
1737 for(i
= 0; i
< 3; i
++) {
1738 global_work_size
[i
] = int_global_work_size
[i
];
1740 free(int_global_work_size
);
1741 } else if(regex_match(key
, "^local_size$")) {
1742 if(!regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1744 uint64_t* int_local_work_size
;
1745 get_uint_array(value
, &int_local_work_size
, 3);
1746 for(i
= 0; i
< 3; i
++) {
1747 local_work_size
[i
] = int_local_work_size
[i
];
1749 local_work_size_null
= false;
1750 free(int_local_work_size
);
1752 local_work_size_null
= true;
1754 } else if(regex_match(key
, "^global_offset$")) {
1755 if(!regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1757 uint64_t* int_global_offset
;
1758 get_uint_array(value
, &int_global_offset
, 3);
1759 for(i
= 0; i
< 3; i
++) {
1760 global_offset
[i
] = int_global_offset
[i
];
1762 global_offset_null
= false;
1763 free(int_global_offset
);
1765 global_offset_null
= true;
1769 "Invalid configuration, key '%s' does not belong to a [config] section: %s\n",
1771 free(key
); key
= NULL
;
1772 free(value
); value
= NULL
;
1773 exit_report_result(PIGLIT_WARN
);
1777 if(regex_match(key
, "^name$")) {
1778 test
->name
= parse_name(value
);
1780 exit_report_result(PIGLIT_FAIL
);
1782 } else if(regex_match(key
, "^kernel_name$")) {
1783 test
->kernel_name
= add_dynamic_str_copy(value
); // test can't have kernel_name == NULL like config section
1784 } else if(regex_match(key
, "^expect_test_fail$")) {
1785 test
->expect_test_fail
= get_bool(value
);
1786 } else if(regex_match(key
, "^dimensions$")) {
1787 test
->work_dimensions
= get_uint(value
);
1788 } else if(regex_match(key
, "^global_size$")) {
1790 uint64_t* int_global_work_size
;
1791 get_uint_array(value
, &int_global_work_size
, 3);
1792 for(i
= 0; i
< 3; i
++) {
1793 test
->global_work_size
[i
] = int_global_work_size
[i
];
1795 free(int_global_work_size
);
1796 } else if(regex_match(key
, "^local_size$")) {
1797 if(!regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1799 uint64_t* int_local_work_size
;
1800 get_uint_array(value
, &int_local_work_size
, 3);
1801 for(i
= 0; i
< 3; i
++) {
1802 test
->local_work_size
[i
] = int_local_work_size
[i
];
1804 test
->local_work_size_null
= false;
1805 free(int_local_work_size
);
1807 test
->local_work_size_null
= true;
1809 } else if(regex_match(key
, "^global_offset$")) {
1810 if(!regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1812 uint64_t* int_global_offset
;
1813 get_uint_array(value
, &int_global_offset
, 3);
1814 for(i
= 0; i
< 3; i
++) {
1815 test
->global_offset
[i
] = int_global_offset
[i
];
1817 test
->global_offset_null
= false;
1818 free(int_global_offset
);
1820 test
->global_offset_null
= true;
1822 } else if(regex_match(key
, "^arg_in$")) {
1823 get_test_arg(value
, test
, true);
1824 } else if(regex_match(key
, "^arg_out$")) {
1825 get_test_arg(value
, test
, false);
1828 "Invalid configuration, key '%s' does not belong to a [test] section: %s\n",
1830 free(key
); key
= NULL
;
1831 free(value
); value
= NULL
;
1832 exit_report_result(PIGLIT_WARN
);
1837 free(key
); key
= NULL
;
1838 free(value
); value
= NULL
;
1839 } else if(!regex_match(line
, REGEX_IGNORE
)){ // not WHITESPACE or COMMENT
1841 "Invalid configuration, configuration could not be parsed: %s\n",
1843 exit_report_result(PIGLIT_WARN
);
1846 /* Go to next line */
1847 free(line
); line
= NULL
;
1848 pch
+= line_length
+1;
1852 fprintf(stderr
, "Invalid configuration, configuration is missing a [config] section.\n");
1853 exit_report_result(PIGLIT_WARN
);
1857 /* Get configuration from comment */
1860 get_comment_config_str(const char* src
)
1862 char* config_str
= NULL
;
1863 regmatch_t pmatch
[2];
1865 if(regex_get_matches(src
, REGEX_COMMENT_CONFIG
, pmatch
, 2, 0)) {
1866 if(regex_get_match_str(&config_str
, src
, pmatch
, 1)) {
1877 init(const int argc
,
1879 struct piglit_cl_program_test_config
* config
)
1881 const char * main_argument
= piglit_cl_get_unnamed_arg(argc
, argv
, 0);
1882 const char * config_file
= NULL
;
1884 char* config_str
= NULL
;
1885 unsigned int config_str_size
;
1886 bool config_arg_present
= piglit_cl_is_arg_defined(argc
, argv
, "config");
1888 enum main_argument_type_t
{
1892 } main_argument_type
;
1896 int program_count
= 0;
1898 /* Check if arguments are valid */
1899 // valid main argument
1900 if(main_argument
== NULL
) {
1902 print_usage(argc
, argv
);
1903 exit_report_result(PIGLIT_WARN
);
1905 print_usage_and_warn(argc
, argv
, "No main argument.");
1908 if(!regex_match(main_argument
, "\\.(cl|program_test|bin)$")) {
1909 print_usage_and_warn(argc
, argv
, "Invalid main argument.");
1911 temp_file
= fopen(main_argument
, "r");
1912 if(temp_file
== NULL
) {
1913 print_usage_and_warn(argc
, argv
, "%s does not exist.", main_argument
);
1916 // valid config argument
1917 if(config_arg_present
) {
1918 config_file
= piglit_cl_get_arg_value(argc
, argv
, "config");
1919 if(!regex_match(config_file
, "\\.program_test$")) {
1920 print_usage_and_warn(argc
, argv
, "Invalid config argument.");
1922 temp_file
= fopen(config_file
, "r");
1923 if(temp_file
== NULL
) {
1924 print_usage_and_warn(argc
, argv
, "%s does not exist.", config_file
);
1928 // no config argument if using .program_test
1929 if(regex_match(main_argument
, "\\.program_test$") && config_arg_present
) {
1930 print_usage_and_warn(argc
,
1932 "Cannot use config argument if main argument is already a config file.");
1935 /* Get main_argument type and config string */
1936 if(regex_match(main_argument
, "\\.program_test$")) {
1937 main_argument_type
= ARG_CONFIG
;
1939 config_file
= main_argument
;
1940 config_str
= piglit_load_text_file(config_file
, &config_str_size
);
1941 } else if(regex_match(main_argument
, "\\.cl$")) {
1942 main_argument_type
= ARG_SOURCE
;
1944 if(config_arg_present
) {
1945 config_file
= piglit_cl_get_arg_value(argc
, argv
, "config");
1946 config_str
= piglit_load_text_file(config_file
, &config_str_size
);
1950 config_file
= main_argument
;
1951 source_str
= piglit_load_text_file(config_file
, &config_str_size
);
1952 config_str
= get_comment_config_str(source_str
);
1956 } else if(regex_match(main_argument
, "\\.bin$")) {
1957 main_argument_type
= ARG_BINARY
;
1959 config_file
= piglit_cl_get_arg_value(argc
, argv
, "config");
1960 config_str
= piglit_load_text_file(config_file
, &config_str_size
);
1962 fprintf(stderr
, "Ops, this should not happen!\n");
1963 exit_report_result(PIGLIT_WARN
);
1966 /* Parse test configuration */
1967 if(config_str
!= NULL
) {
1968 parse_config(config_str
, config
);
1971 fprintf(stderr
, "No configuration found.\n");
1975 switch(main_argument_type
) {
1977 if( config
->program_source_file
!= NULL
1978 || config
->program_binary_file
!= NULL
) {
1979 const char* program_file
= NULL
;
1980 char* main_arg_copy
= NULL
;
1982 char* full_path_file
= NULL
;
1984 if(config
->program_source_file
!= NULL
) {
1985 program_file
= config
->program_source_file
;
1987 program_file
= config
->program_binary_file
;
1990 main_arg_copy
= strdup(main_argument
);
1991 dname
= dirname(main_arg_copy
);
1992 full_path_file
= malloc(strlen(dname
) + strlen(program_file
) + 2); // +2 for '/' and '\0'
1993 strcpy(full_path_file
, dname
);
1994 full_path_file
[strlen(dname
)] = '/';
1995 strcpy(full_path_file
+strlen(dname
)+1, program_file
);
1997 if(config
->program_source_file
!= NULL
) {
1998 config
->program_source_file
= full_path_file
;
2000 config
->program_binary_file
= full_path_file
;
2003 add_dynamic_str(full_path_file
);
2004 free(main_arg_copy
);
2008 config
->program_source_file
= add_dynamic_str_copy(main_argument
);
2011 config
->program_binary_file
= add_dynamic_str_copy(main_argument
);
2015 /* Check if there is one program_* set */
2016 if(config
->program_source
!= NULL
) program_count
++;
2017 if(config
->program_source_file
!= NULL
) program_count
++;
2018 if(config
->program_binary
!= NULL
) program_count
++;
2019 if(config
->program_binary_file
!= NULL
) program_count
++;
2020 if(program_count
== 0) {
2021 fprintf(stderr
, "Invalid configuration, no program defined.\n");
2022 exit_report_result(PIGLIT_WARN
);
2023 } else if (program_count
> 1) {
2024 fprintf(stderr
, "Invalid configuration, multiple programs defined.\n");
2025 exit_report_result(PIGLIT_WARN
);
2028 /* Run test per device */
2029 config
->run_per_device
= true;
2032 /* Memory object functions */
2037 cl_mem_object_type type
;
2041 free_mem_args(struct mem_arg
** mem_args
, unsigned int* num_mem_args
)
2045 for(i
= 0; i
< *num_mem_args
; i
++) {
2046 clReleaseMemObject((*mem_args
)[i
].mem
);
2049 free(*mem_args
); *mem_args
= NULL
;
2054 free_sampler_args(cl_sampler
** sampler_args
, unsigned int* num_sampler_args
)
2058 for(i
= 0; i
< *num_sampler_args
; i
++) {
2059 clReleaseSampler((*sampler_args
)[i
]);
2062 free(*sampler_args
); *sampler_args
= NULL
;
2063 *num_sampler_args
= 0;
2067 check_test_arg_value(struct test_arg test_arg
,
2070 size_t i
; // index in array
2071 size_t c
; // component in element
2072 size_t ra
; // offset from the beginning of parsed array
2073 size_t rb
; // offset from the beginning of buffer
2075 #define CASEI(enum_type, type, cl_type) \
2077 for(i = 0; i < test_arg.length; i++) { \
2078 for(c = 0; c < test_arg.cl_size; c++) { \
2079 rb = i*test_arg.cl_mem_size + c; \
2080 if(!piglit_cl_probe_integer(((cl_type*)value)[rb], \
2081 ((cl_type*)test_arg.value)[rb], \
2083 ra = i*test_arg.cl_size + c; \
2084 printf("Error at %s[%zu]\n", type, ra); \
2090 #define CASEU(enum_type, type, cl_type) \
2092 for(i = 0; i < test_arg.length; i++) { \
2093 for(c = 0; c < test_arg.cl_size; c++) { \
2094 rb = i*test_arg.cl_mem_size + c; \
2095 if(!piglit_cl_probe_uinteger(((cl_type*)value)[rb], \
2096 ((cl_type*)test_arg.value)[rb], \
2098 ra = i*test_arg.cl_size + c; \
2099 printf("Error at %s[%zu]\n", type, ra); \
2105 #define CASEH(enum_type, type, cl_type) \
2107 for(i = 0; i < test_arg.length; i++) { \
2108 for(c = 0; c < test_arg.cl_size; c++) { \
2109 rb = i*test_arg.cl_mem_size + c; \
2110 if(!piglit_cl_probe_half(((cl_type*)value)[rb], \
2111 ((cl_type*)test_arg.value)[rb], \
2113 ra = i*test_arg.cl_size + c; \
2114 printf("Error at %s[%zu]\n", type, ra); \
2120 #define CASEF(enum_type, type, cl_type, testfn) \
2122 for(i = 0; i < test_arg.length; i++) { \
2123 for(c = 0; c < test_arg.cl_size; c++) { \
2124 rb = i*test_arg.cl_mem_size + c; \
2125 if(!testfn(((cl_type*)value)[rb], \
2126 ((cl_type*)test_arg.value)[rb], \
2128 ra = i*test_arg.cl_size + c; \
2129 printf("Error at %s[%zu]\n", type, ra); \
2136 switch(test_arg
.cl_type
) {
2137 CASEI(TYPE_CHAR
, "char", cl_char
)
2138 CASEU(TYPE_UCHAR
, "uchar", cl_uchar
)
2139 CASEI(TYPE_SHORT
, "short", cl_short
)
2140 CASEU(TYPE_USHORT
, "ushort", cl_ushort
)
2141 CASEI(TYPE_INT
, "int", cl_int
)
2142 CASEU(TYPE_UINT
, "uint", cl_uint
)
2143 CASEI(TYPE_LONG
, "long", cl_long
)
2144 CASEU(TYPE_ULONG
, "ulong", cl_ulong
)
2145 CASEH(TYPE_HALF
, "half", cl_half
)
2146 CASEF(TYPE_FLOAT
, "float", cl_float
, piglit_cl_probe_floating
)
2147 CASEF(TYPE_DOUBLE
, "double", cl_double
, piglit_cl_probe_double
)
2157 /* Run the kernel test */
2159 test_kernel(const struct piglit_cl_program_test_config
* config
,
2160 const struct piglit_cl_program_test_env
* env
,
2163 enum piglit_result result
= PIGLIT_PASS
;
2170 // setting/validating arguments
2171 struct mem_arg
* mem_args
= NULL
;
2172 unsigned int num_mem_args
= 0;
2174 cl_sampler
*sampler_args
= NULL
;
2175 unsigned int num_sampler_args
= 0;
2177 /* Check if this device supports the local work size. */
2178 if (!piglit_cl_framework_check_local_work_size(env
->device_id
,
2179 test
.local_work_size
)) {
2183 /* Create or use apropriate kernel */
2184 if(test
.kernel_name
== NULL
) {
2185 kernel_name
= config
->kernel_name
;
2186 kernel
= env
->kernel
;
2188 if(config
->kernel_name
== NULL
) {
2189 printf("No kernel_name defined\n");
2192 clRetainKernel(kernel
);
2195 kernel_name
= test
.kernel_name
;
2196 kernel
= piglit_cl_create_kernel(env
->program
, test
.kernel_name
);
2198 if(kernel
== NULL
) {
2199 printf("Could not create kernel %s\n", kernel_name
);
2204 printf("Using kernel %s\n", kernel_name
);
2206 /* Set kernel args */
2207 printf("Setting kernel arguments...\n");
2209 for(j
= 0; j
< test
.num_args_in
; j
++) {
2210 bool arg_set
= false;
2211 struct test_arg test_arg
= test
.args_in
[j
];
2213 switch(test_arg
.type
) {
2214 case TEST_ARG_VALUE
:
2215 arg_set
= piglit_cl_set_kernel_arg(kernel
,
2220 case TEST_ARG_BUFFER
: {
2221 struct mem_arg mem_arg
;
2222 mem_arg
.index
= test_arg
.index
;
2223 mem_arg
.type
= CL_MEM_OBJECT_BUFFER
;
2225 if(test_arg
.value
!= NULL
) {
2226 mem_arg
.mem
= piglit_cl_create_buffer(env
->context
,
2229 if( mem_arg
.mem
!= NULL
2230 && piglit_cl_write_buffer(env
->context
->command_queues
[0],
2235 && piglit_cl_set_kernel_arg(kernel
,
2243 arg_set
= piglit_cl_set_kernel_arg(kernel
,
2250 add_dynamic_array((void**)&mem_args
,
2252 sizeof(struct mem_arg
),
2257 case TEST_ARG_IMAGE
: {
2258 struct mem_arg mem_arg
;
2259 mem_arg
.index
= test_arg
.index
;
2260 mem_arg
.type
= test_arg
.image_desc
.image_type
;
2262 if(!test_arg
.value
) {
2263 printf("Image argument cannot be null.\n");
2268 mem_arg
.mem
= piglit_cl_create_image(env
->context
,
2270 &test_arg
.image_format
,
2271 &test_arg
.image_desc
);
2272 if( mem_arg
.mem
!= NULL
2273 && piglit_cl_write_whole_image(env
->context
->command_queues
[0],
2276 && piglit_cl_set_kernel_arg(kernel
,
2284 add_dynamic_array((void**)&mem_args
,
2286 sizeof(struct mem_arg
),
2291 case TEST_ARG_SAMPLER
: {
2292 cl_sampler sampler
= piglit_cl_create_sampler(
2294 test_arg
.sampler_normalized_coords
,
2295 test_arg
.sampler_addressing_mode
,
2296 test_arg
.sampler_filter_mode
);
2303 arg_set
= piglit_cl_set_kernel_arg(kernel
,
2309 add_dynamic_array((void**)&sampler_args
,
2318 printf("Failed to set kernel argument with index %u\n",
2320 clReleaseKernel(kernel
);
2321 free_mem_args(&mem_args
, &num_mem_args
);
2322 free_sampler_args(&sampler_args
, &num_sampler_args
);
2327 for(j
= 0; j
< test
.num_args_out
; j
++) {
2328 bool arg_set
= false;
2329 struct test_arg test_arg
= test
.args_out
[j
];
2331 switch(test_arg
.type
) {
2332 case TEST_ARG_VALUE
:
2333 // not accepted by parser
2335 case TEST_ARG_BUFFER
: {
2338 struct mem_arg mem_arg
;
2339 mem_arg
.index
= test_arg
.index
;
2340 mem_arg
.type
= CL_MEM_OBJECT_BUFFER
;
2342 for(k
= 0; k
< num_mem_args
; k
++) {
2343 if(mem_args
[k
].index
!= mem_arg
.index
)
2346 if(mem_args
[k
].type
!= mem_arg
.type
) {
2347 printf("Inconsistent types specified for in-out"
2348 "argument %d: arg_in: %s, arg_out: %s.\n",
2350 piglit_cl_get_enum_name(mem_args
[k
].type
),
2351 piglit_cl_get_enum_name(mem_arg
.type
));
2358 if(arg_set
|| fail
) {
2362 if(test_arg
.value
!= NULL
) {
2363 mem_arg
.mem
= piglit_cl_create_buffer(env
->context
,
2366 if( mem_arg
.mem
!= NULL
2367 && piglit_cl_set_kernel_arg(kernel
,
2375 arg_set
= piglit_cl_set_kernel_arg(kernel
,
2382 add_dynamic_array((void**)&mem_args
,
2384 sizeof(struct mem_arg
),
2389 case TEST_ARG_IMAGE
: {
2392 struct mem_arg mem_arg
;
2393 mem_arg
.index
= test_arg
.index
;
2394 mem_arg
.type
= test_arg
.image_desc
.image_type
;
2396 for(k
= 0; k
< num_mem_args
; k
++) {
2397 if(mem_args
[k
].index
== mem_arg
.index
) {
2398 printf("Argument %d: images cannot be in-out arguments.",
2409 if(!test_arg
.value
) {
2410 printf("Image argument cannot be null.\n");
2415 mem_arg
.mem
= piglit_cl_create_image(env
->context
,
2417 &test_arg
.image_format
,
2418 &test_arg
.image_desc
);
2419 if( mem_arg
.mem
!= NULL
2420 && piglit_cl_set_kernel_arg(kernel
,
2428 add_dynamic_array((void**)&mem_args
,
2430 sizeof(struct mem_arg
),
2435 case TEST_ARG_SAMPLER
:
2436 // not accepted by parser
2441 printf("Failed to set kernel argument with index %u\n",
2443 clReleaseKernel(kernel
);
2444 free_mem_args(&mem_args
, &num_mem_args
);
2445 free_sampler_args(&sampler_args
, &num_sampler_args
);
2450 /* Execute kernel */
2451 printf("Running the kernel...\n");
2453 if(!piglit_cl_execute_ND_range_kernel(env
->context
->command_queues
[0],
2455 test
.work_dimensions
,
2456 test
.global_offset_null
? NULL
: test
.global_offset
,
2457 test
.global_work_size
,
2458 test
.local_work_size_null
? NULL
: test
.local_work_size
)) {
2459 printf("Failed to enqueue the kernel\n");
2460 clReleaseKernel(kernel
);
2461 free_mem_args(&mem_args
, &num_mem_args
);
2462 free_sampler_args(&sampler_args
, &num_sampler_args
);
2467 printf("Validating results...\n");
2469 for(j
= 0; j
< test
.num_args_out
; j
++) {
2471 bool arg_valid
= false;
2472 struct test_arg test_arg
= test
.args_out
[j
];
2474 switch(test_arg
.type
) {
2475 case TEST_ARG_VALUE
:
2476 // Not accepted by parser
2478 case TEST_ARG_BUFFER
: {
2479 struct mem_arg mem_arg
;
2481 /* Find the right buffer */
2482 for(k
= 0; k
< num_mem_args
; k
++) {
2483 if(mem_args
[k
].index
== test_arg
.index
) {
2484 mem_arg
= mem_args
[k
];
2488 if(test_arg
.value
!= NULL
) {
2489 void* read_value
= malloc(test_arg
.size
);
2491 if(piglit_cl_read_buffer(env
->context
->command_queues
[0],
2497 if(check_test_arg_value(test_arg
, read_value
)) {
2498 printf(" Argument %u: PASS%s\n",
2500 !test
.expect_test_fail
? "" : " (not expected)");
2501 if(test
.expect_test_fail
) {
2502 piglit_merge_result(&result
, PIGLIT_FAIL
);
2505 printf(" Argument %u: FAIL%s\n",
2507 !test
.expect_test_fail
? "" : " (expected)");
2508 if(!test
.expect_test_fail
) {
2509 piglit_merge_result(&result
, PIGLIT_FAIL
);
2519 case TEST_ARG_IMAGE
: {
2520 struct mem_arg mem_arg
;
2522 /* Find the right buffer */
2523 for(k
= 0; k
< num_mem_args
; k
++) {
2524 if(mem_args
[k
].index
== test_arg
.index
) {
2525 mem_arg
= mem_args
[k
];
2529 if(test_arg
.value
!= NULL
) {
2530 void* read_value
= malloc(test_arg
.size
);
2532 if(piglit_cl_read_whole_image(env
->context
->command_queues
[0],
2536 if(check_test_arg_value(test_arg
, read_value
)) {
2537 printf(" Argument %u: PASS%s\n",
2539 !test
.expect_test_fail
? "" : " (not expected)");
2540 if(test
.expect_test_fail
) {
2541 piglit_merge_result(&result
, PIGLIT_FAIL
);
2544 printf(" Argument %u: FAIL%s\n",
2546 !test
.expect_test_fail
? "" : " (expected)");
2547 if(!test
.expect_test_fail
) {
2548 piglit_merge_result(&result
, PIGLIT_FAIL
);
2558 case TEST_ARG_SAMPLER
:
2559 // Not accepted by parser
2564 printf("Failed to validate kernel argument with index %u\n",
2566 clReleaseKernel(kernel
);
2567 free_mem_args(&mem_args
, &num_mem_args
);
2568 free_sampler_args(&sampler_args
, &num_sampler_args
);
2573 /* Clean memory used by test */
2574 clReleaseKernel(kernel
);
2575 free_mem_args(&mem_args
, &num_mem_args
);
2576 free_sampler_args(&sampler_args
, &num_sampler_args
);
2583 piglit_cl_test(const int argc
,
2585 const struct piglit_cl_program_test_config
* config
,
2586 const struct piglit_cl_program_test_env
* env
)
2588 enum piglit_result result
= PIGLIT_SKIP
;
2592 /* Print building status */
2593 if(!config
->expect_build_fail
) {
2594 printf("Program has been built successfully\n");
2596 printf("Program has failed to build as expected\n");
2599 /* If num_tests is 0, then we are running a build test and the fact
2600 * that we have made it this far means that the program has built
2601 * successfully, so we can report PIGLIT_PASS.
2603 if (num_tests
== 0) {
2604 result
= PIGLIT_PASS
;
2608 for(i
= 0; i
< num_tests
; i
++) {
2609 enum piglit_result test_result
;
2610 char* test_name
= tests
[i
].name
!= NULL
? tests
[i
].name
: "";
2612 printf("> Running kernel test: %s\n", test_name
);
2614 test_result
= test_kernel(config
, env
, tests
[i
]);
2615 piglit_merge_result(&result
, test_result
);
2617 piglit_report_subtest_result(test_result
, "%s", tests
[i
].name
);
2624 printf(">> Some or all of the tests FAILED\n");
2627 printf(">> Tests skipped\n");
2630 printf(">> Some or all of the tests produced a WARNING\n");
2633 printf(">> All of the tests PASSED\n");