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.
35 #include "piglit-framework-cl-program.h"
45 * Watch on subexpressions when modifying regexes, because some of them are
46 * used to retrieve the strings matching them!
50 * Section (section can include whitespace):
51 * <whitespace>[<whitespace>section<whitespace>]<whitespace>
53 #define REGEX_SECTION "^[[:space:]]*\\[[[:space:]]*([[:alnum:]_]+[[:alnum:][:space:]_]*[[:alnum:]_]+|[[:alnum:]_]+)[[:space:]]*\\][[:space:]]*$" /* section */
55 * Key-value (value can have whitespace):
56 * <whitespace>key<whitespace>:<whitespace>value<whitespace>
58 #define REGEX_KEY_VALUE "^[[:space:]]*([[:alnum:]_]+)[[:space:]]*" /* key */ \
60 "[[:space:]]*([^[:space:]#]+[^#]*[^[:space:]#]+|[^[:space:]#]+)[[:space:]]*$" /* value */
65 #define REGEX_IGNORE "^[[:space:]]*$"
68 #define REGEX_ARRAY_DELIMITER "[[:space:]]+"
69 #define REGEX_DEFINE_ARRAY(element) "((" element REGEX_ARRAY_DELIMITER ")*" element ")"
70 #define REGEX_NAN "(nan|NAN|NaN)"
71 #define REGEX_PNAN "([+]?" REGEX_NAN ")"
72 #define REGEX_NNAN "([-]" REGEX_NAN ")"
73 #define REGEX_INF "(infinity|INFINITY|Infinity|inf|INF|Inf)"
74 #define REGEX_PINF "([+]?" REGEX_INF ")"
75 #define REGEX_NINF "([-]" REGEX_INF ")"
76 #define REGEX_NULL "(NULL|null)"
77 #define REGEX_BOOL "(0|1|false|true)"
78 #define REGEX_BOOL_TRUE "(1|true)"
79 #define REGEX_BOOL_FALSE "(0|false)"
80 #define REGEX_INT "(([+-]?[[:digit:]]+)|([+-]?0[Xx][[:digit:]abcdefABCDEF]+))"
81 #define REGEX_UINT "(([+]?[[:digit:]]+)|([+]?0[Xx][[:digit:]abcdefABCDEF]+))"
82 #define REGEX_FLOAT_HEX "([+-]?0[Xx][[:digit:]abcdefABCDEF.]+[[:digit:]pP+-]*)"
83 #define REGEX_FLOAT "(([+-]?[[:digit:]]+(\\.[[:digit:]]+)?e*[+-]*[[:digit:]]*)|" \
84 REGEX_FLOAT_HEX "|" REGEX_PNAN "|" REGEX_NNAN "|" REGEX_PINF "|" \
86 #define REGEX_BOOL_ARRAY REGEX_DEFINE_ARRAY(REGEX_BOOL)
87 #define REGEX_INT_ARRAY REGEX_DEFINE_ARRAY(REGEX_INT)
88 #define REGEX_UINT_ARRAY REGEX_DEFINE_ARRAY(REGEX_UINT)
89 #define REGEX_FLOAT_ARRAY REGEX_DEFINE_ARRAY(REGEX_FLOAT)
90 #define REGEX_VALUE "(" REGEX_NULL "|" REGEX_BOOL "|" REGEX_INT "|" \
91 REGEX_UINT "|" REGEX_FLOAT ")"
92 #define REGEX_ARRAY "(" REGEX_NULL "|" REGEX_BOOL_ARRAY "|" \
93 REGEX_INT_ARRAY "|" REGEX_UINT_ARRAY "|" \
95 #define REGEX_ARRAY_VALUE "(" REGEX_BOOL "|" REGEX_INT "|" REGEX_UINT "|" \
97 #define REGEX_RANDOM "(RANDOM|random)"
98 #define REGEX_REPEAT "(REPEAT|repeat)[[:space:]]+" \
99 REGEX_DEFINE_ARRAY(REGEX_ARRAY_VALUE)
102 #define REGEX_DEFINE_TYPE(type) type"|"type"2|"type"3|"type"4|"type"8|"type"16"
103 #define REGEX_TYPE_CHAR REGEX_DEFINE_TYPE("char")
104 #define REGEX_TYPE_UCHAR REGEX_DEFINE_TYPE("uchar")
105 #define REGEX_TYPE_SHORT REGEX_DEFINE_TYPE("short")
106 #define REGEX_TYPE_USHORT REGEX_DEFINE_TYPE("ushort")
107 #define REGEX_TYPE_INT REGEX_DEFINE_TYPE("int")
108 #define REGEX_TYPE_UINT REGEX_DEFINE_TYPE("uint")
109 #define REGEX_TYPE_LONG REGEX_DEFINE_TYPE("long")
110 #define REGEX_TYPE_ULONG REGEX_DEFINE_TYPE("ulong")
111 // half is defined as unsigned short and C can't read/write its value.
112 // Also half is only used as a storage format unless device supports
114 // TODO: probably we could use libmpdec to handle this
115 // http://www.bytereef.org/mpdecimal/index.html
116 //#define REGEX_TYPE_HALF "buffer half[1]"
117 #define REGEX_TYPE_HALF REGEX_DEFINE_TYPE("half")
118 #define REGEX_TYPE_FLOAT REGEX_DEFINE_TYPE("float")
119 #define REGEX_TYPE_DOUBLE REGEX_DEFINE_TYPE("double")
120 #define REGEX_TYPE REGEX_TYPE_CHAR "|" REGEX_TYPE_UCHAR "|" \
121 REGEX_TYPE_SHORT "|" REGEX_TYPE_USHORT "|" \
122 REGEX_TYPE_INT "|" REGEX_TYPE_UINT "|" \
123 REGEX_TYPE_LONG "|" REGEX_TYPE_ULONG "|" \
124 REGEX_TYPE_HALF "|" REGEX_TYPE_FLOAT "|" REGEX_TYPE_DOUBLE
127 /* TODO: add OpenCL 1.2+ types */
128 #define REGEX_IMGT_2D "2D|2d"
129 #define REGEX_IMGT_3D "3D|3d"
130 #define REGEX_IMAGE_TYPE REGEX_IMGT_2D "|" REGEX_IMGT_3D
133 /* TODO: add OpenCL 2.0 formats */
134 #define REGEX_CHO_R "R|r"
135 #define REGEX_CHO_RX "RX|Rx|rx"
136 #define REGEX_CHO_A "A|a"
137 #define REGEX_CHO_INTENSITY "INTENSITY|intensity"
138 #define REGEX_CHO_LUMINANCE "LUMINANCE|luminance"
139 #define REGEX_CHO_RG "RG|rg"
140 #define REGEX_CHO_RGX "RGX|RGx|rgx"
141 #define REGEX_CHO_RA "RA|ra"
142 #define REGEX_CHO_RGB "RGB|rgb"
143 #define REGEX_CHO_RGBX "RGBX|rgbx"
144 #define REGEX_CHO_RGBA "RGBA|rgba"
145 #define REGEX_CHO_ARGB "ARGB|argb"
146 #define REGEX_CHO_BGRA "BGRA|bgra"
147 #define REGEX_CHANNEL_ORDER REGEX_CHO_R "|" REGEX_CHO_RX "|" REGEX_CHO_A "|" \
148 REGEX_CHO_INTENSITY "|" REGEX_CHO_LUMINANCE "|" \
149 REGEX_CHO_RG "|" REGEX_CHO_RGX "|" \
150 REGEX_CHO_RA "|" REGEX_CHO_RGB "|" \
151 REGEX_CHO_RGBX "|" REGEX_CHO_RGBA "|" \
152 REGEX_CHO_ARGB "|" REGEX_CHO_BGRA
154 #define REGEX_CHT_SNORM_INT8 "SNORM_INT8|snorm_int8"
155 #define REGEX_CHT_SNORM_INT16 "SNORM_INT16|snorm_int16"
156 #define REGEX_CHT_UNORM_INT8 "UNORM_INT8|unorm_int8"
157 #define REGEX_CHT_UNORM_INT16 "UNORM_INT16|unorm_int16"
158 #define REGEX_CHT_UNORM_SHORT_565 "UNORM_SHORT_565|unorm_short_565"
159 #define REGEX_CHT_UNORM_SHORT_555 "UNORM_SHORT_555|unorm_short_555"
160 #define REGEX_CHT_UNORM_INT_101010 "UNORM_INT_101010|unorm_int_101010"
161 #define REGEX_CHT_SIGNED_INT8 "SIGNED_INT8|signed_int8"
162 #define REGEX_CHT_SIGNED_INT16 "SIGNED_INT16|signed_int16"
163 #define REGEX_CHT_SIGNED_INT32 "SIGNED_INT32|signed_int32"
164 #define REGEX_CHT_UNSIGNED_INT8 "UNSIGNED_INT8|unsigned_int8"
165 #define REGEX_CHT_UNSIGNED_INT16 "UNSIGNED_INT16|unsigned_int16"
166 #define REGEX_CHT_UNSIGNED_INT32 "UNSIGNED_INT32|unsigned_int32"
167 #define REGEX_CHT_HALF_FLOAT "HALF_FLOAT|half_float"
168 #define REGEX_CHT_FLOAT "FLOAT|float"
169 #define REGEX_CHANNEL_DATA_TYPE REGEX_CHT_SNORM_INT8 "|" \
170 REGEX_CHT_SNORM_INT16 "|" \
171 REGEX_CHT_UNORM_INT8 "|" \
172 REGEX_CHT_UNORM_INT16 "|" \
173 REGEX_CHT_UNORM_SHORT_565 "|" \
174 REGEX_CHT_UNORM_SHORT_555 "|" \
175 REGEX_CHT_UNORM_INT_101010 "|" \
176 REGEX_CHT_SIGNED_INT8 "|" \
177 REGEX_CHT_SIGNED_INT16 "|" \
178 REGEX_CHT_SIGNED_INT32 "|" \
179 REGEX_CHT_UNSIGNED_INT8 "|" \
180 REGEX_CHT_UNSIGNED_INT16 "|" \
181 REGEX_CHT_UNSIGNED_INT32 "|" \
182 REGEX_CHT_HALF_FLOAT "|" \
186 #define REGEX_SAMP_ADDR_NONE "NONE|none"
187 #define REGEX_SAMP_ADDR_CLAMP_TO_EDGE "CLAMP_TO_EDGE|clamp_to_edge"
188 #define REGEX_SAMP_ADDR_CLAMP "CLAMP|clamp"
189 #define REGEX_SAMP_ADDR_REPEAT "REPEAT|repeat"
190 #define REGEX_SAMP_ADDR_MIRRORED_REPEAT "MIRRORED_REPEAT|mirrored_repeat"
191 #define REGEX_SAMPLER_ADDRESSING_MODE REGEX_SAMP_ADDR_NONE "|"\
192 REGEX_SAMP_ADDR_CLAMP_TO_EDGE "|" \
193 REGEX_SAMP_ADDR_CLAMP "|" \
194 REGEX_SAMP_ADDR_REPEAT "|" \
195 REGEX_SAMP_ADDR_MIRRORED_REPEAT
197 #define REGEX_SAMP_FILT_NEAREST "NEAREST|nearest"
198 #define REGEX_SAMP_FILT_LINEAR "LINEAR|linear"
199 #define REGEX_SAMPLER_FILTER_MODE REGEX_SAMP_FILT_NEAREST "|" \
200 REGEX_SAMP_FILT_LINEAR
204 * index<whitespace>type<whitespace>value
206 * index<whitespace>buffer<whitespace>type[size]<whitespace>(value|random|repeat value)<whitespace>tolerance<whitespace>value
208 * index<whitespace>image<whitespace>type<whitespace>
209 * (value|random|repeat value)<whitespace>
210 * image_type<whitespace>(2d|3d)<whitespace>i
211 * image_width<whitespace>value<whitespace>
212 * image_height<whitespace>value<whitespace>
213 * image_channel_order<whitespace>value<whitespace>
214 * image_channel_data_type<whitespace>value<whitespace>
215 * tolerance<whitespace>value
217 * index<whitespace>sampler<whitespace>
218 * normalized_coords<whitespace>bool<whitespace>
219 * addressing_mode<whitespace>(none|clamp_to_edge|repeat|mirrored_repeat)<whitespace>
220 * filter_mode<whitespace>(nearest|linear)<whitespace>
222 #define REGEX_DEFINE_ARG(type, value) "([[:digit:]]+)[[:space:]]+" type \
223 "[[:space:]]+(" value ")"
224 #define REGEX_ARG_TOLERANCE "tolerance[[:space:]]+(" REGEX_VALUE ")"
225 #define REGEX_ARG_TOLERANCE_ULP REGEX_ARG_TOLERANCE "[[:space:]]+ulp"
226 #define REGEX_ARG_IMAGE_TYPE "image_type[[:space:]]+(" REGEX_IMAGE_TYPE ")"
227 #define REGEX_ARG_IMAGE_WIDTH "image_width[[:space:]]+(" REGEX_UINT ")"
228 #define REGEX_ARG_IMAGE_HEIGHT "image_height[[:space:]]+(" REGEX_UINT ")"
229 #define REGEX_ARG_IMAGE_CHANNEL_ORDER "image_channel_order[[:space:]]+(" REGEX_CHANNEL_ORDER ")"
230 #define REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE "image_channel_data_type[[:space:]]+(" REGEX_CHANNEL_DATA_TYPE ")"
231 #define REGEX_ARG_SAMPLER_NORMALIZED_COORDS "normalized_coords[[:space:]]+" REGEX_BOOL
232 #define REGEX_ARG_SAMPLER_ADDERSSING_MODE "addressing_mode[[:space:]]+(" REGEX_SAMPLER_ADDRESSING_MODE ")"
233 #define REGEX_ARG_SAMPLER_FILTER_MODE "filter_mode[[:space:]]+(" REGEX_SAMPLER_FILTER_MODE ")"
234 #define REGEX_ARG_VALUE REGEX_DEFINE_ARG( "(" REGEX_TYPE ")", REGEX_ARRAY )
235 #define REGEX_ARG_BUFFER REGEX_DEFINE_ARG( "buffer[[:space:]]+(" REGEX_TYPE ")\\[([[:digit:]]+)\\]", \
236 REGEX_ARRAY "|" REGEX_RANDOM "|" REGEX_REPEAT ) \
237 "([[:space:]]+" "("REGEX_ARG_TOLERANCE "|" REGEX_ARG_TOLERANCE_ULP")" ")?"
238 #define REGEX_ARG_IMAGE REGEX_DEFINE_ARG( "image[[:space:]]+(" REGEX_TYPE ")", \
239 REGEX_ARRAY "|" REGEX_RANDOM "|" REGEX_REPEAT ) \
240 "[[:space:]]+"REGEX_ARG_IMAGE_TYPE \
241 "[[:space:]]+"REGEX_ARG_IMAGE_WIDTH \
242 "[[:space:]]+"REGEX_ARG_IMAGE_HEIGHT \
243 "[[:space:]]+"REGEX_ARG_IMAGE_CHANNEL_ORDER \
244 "[[:space:]]+"REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE \
245 "([[:space:]]+" "("REGEX_ARG_TOLERANCE "|" REGEX_ARG_TOLERANCE_ULP")" ")?"
246 #define REGEX_ARG_SAMPLER "([[:digit:]]+)[[:space:]]+sampler" \
247 "[[:space:]]+"REGEX_ARG_SAMPLER_NORMALIZED_COORDS \
248 "[[:space:]]+"REGEX_ARG_SAMPLER_ADDERSSING_MODE \
249 "[[:space:]]+"REGEX_ARG_SAMPLER_FILTER_MODE
250 #define REGEX_ARG "(" REGEX_ARG_VALUE "|" REGEX_ARG_BUFFER "|" \
251 REGEX_ARG_IMAGE "|" REGEX_ARG_SAMPLER ")"
253 /* Match whole line */
254 #define REGEX_FULL_MATCH(content) "^"content"$"
257 #define REGEX_COMMENT_CONFIG "/\\*!(.*)!\\*/"
260 #define REGEX_LINE "^([^#]*)(#.*)?$"
261 #define REGEX_MULTILINE "^([^#]*)\\\\[[:space:]]*$"
263 /* Config function */
264 void init(const int argc
,
266 struct piglit_cl_program_test_config
* config
);
267 void clean(const int argc
,
269 const struct piglit_cl_program_test_config
* config
);
272 /* Kernel test configuration */
275 PIGLIT_CL_PROGRAM_TEST_CONFIG_BEGIN
277 config
.init_func
= (piglit_cl_test_init_t
*)init
;
278 config
.clean_func
= (piglit_cl_test_clean_t
*)clean
;
280 PIGLIT_CL_PROGRAM_TEST_CONFIG_END
282 // Additional options
283 bool expect_test_fail
= false;
284 cl_uint work_dimensions
= 1;
285 size_t global_work_size
[3] = {1, 1, 1};
286 size_t local_work_size
[3] = {1, 1, 1};
287 size_t global_offset
[3] = {0, 0, 0};
288 bool local_work_size_null
= false;
289 bool global_offset_null
= true;
291 /* Helper functions */
294 add_dynamic_array(void** array
,
300 if(((*count
)%GROW_SIZE
) == 0) {
301 void* old_array
= *array
;
303 *array
= malloc(((*count
)/GROW_SIZE
+ 1)*GROW_SIZE
* element_size
);
304 memcpy(*array
, old_array
, (*count
) * element_size
);
309 memcpy((char *)(*array
) + ((*count
)*element_size
), data
, element_size
);
338 enum test_arg_type type
;
340 enum cl_type cl_type
;
341 size_t cl_size
; // 1 for int, 3 for int3
342 size_t cl_mem_size
; // 1 for int, 4 for int3
343 size_t length
; // for buffers
345 /* kernel arg data */
356 piglit_image_desc image_desc
;
357 cl_image_format image_format
;
360 cl_bool sampler_normalized_coords
;
361 cl_addressing_mode sampler_addressing_mode
;
362 cl_filter_mode sampler_filter_mode
;
365 struct test_arg
create_test_arg()
367 struct test_arg ta
= {
368 .type
= TEST_ARG_VALUE
,
370 .cl_type
= TYPE_CHAR
,
391 cl_uint work_dimensions
;
392 size_t global_work_size
[3];
393 size_t local_work_size
[3];
394 bool local_work_size_null
;
395 size_t global_offset
[3];
396 bool global_offset_null
;
398 bool expect_test_fail
;
400 unsigned int num_args_in
;
401 struct test_arg
* args_in
;
403 unsigned int num_args_out
;
404 struct test_arg
* args_out
;
407 unsigned int num_tests
= 0;
408 struct test
* tests
= NULL
;
410 struct test
create_test()
416 .work_dimensions
= work_dimensions
,
417 //.global_work_size = global_work_size,
418 //.local_work_size = local_work_size,
419 .local_work_size_null
= local_work_size_null
,
420 .global_offset_null
= global_offset_null
,
422 .expect_test_fail
= expect_test_fail
,
431 memcpy(t
.global_work_size
, global_work_size
, sizeof(global_work_size
));
432 memcpy(t
.local_work_size
, local_work_size
, sizeof(local_work_size
));
433 memcpy(t
.global_offset
, global_offset
, sizeof(global_offset
));
439 add_test(struct test t
)
441 add_dynamic_array((void**)&tests
, &num_tests
, sizeof(struct test
), &t
);
445 add_test_arg(struct test
* t
, struct test_arg ta
, bool arg_in
)
448 struct test_arg
* this_args
;
449 size_t num_this_args
;
450 struct test_arg
* other_args
;
451 size_t num_other_args
;
454 this_args
= t
->args_in
;
455 num_this_args
= t
->num_args_in
;
456 other_args
= t
->args_out
;
457 num_other_args
= t
->num_args_out
;
459 this_args
= t
->args_out
;
460 num_this_args
= t
->num_args_out
;
461 other_args
= t
->args_in
;
462 num_other_args
= t
->num_args_in
;
465 // Check that argument is new
466 for(i
= 0; i
< num_this_args
; i
++) {
467 struct test_arg ta_this
= this_args
[i
];
469 if(ta
.index
== ta_this
.index
) {
471 "Invalid configuration, %s argument with index %d is already defined\n",
472 arg_in
? "In" : "Out",
477 // Check that types correspond
478 for(i
= 0; i
< num_other_args
; i
++) {
479 struct test_arg ta_other
= other_args
[i
];
481 if(ta
.index
== ta_other
.index
) {
482 if(ta
.type
!= ta_other
.type
) {
484 "Invalid configuration, in argument at index %d isn't compatible with out argument\n",
488 if(ta
.size
!= ta_other
.size
) {
490 "Invalid configuration, Size of in argument (%zu) at index %d isn't the same as size of out argument (%zu)\n",
491 arg_in
? ta
.size
: ta_other
.size
,
493 arg_in
? ta_other
.size
: ta
.size
);
500 add_dynamic_array((void**)&t
->args_in
,
502 sizeof(struct test_arg
),
505 add_dynamic_array((void**)&t
->args_out
,
507 sizeof(struct test_arg
),
515 add_test_arg_in(struct test
* t
, struct test_arg ta
)
517 return add_test_arg(t
, ta
, true);
521 add_test_arg_out(struct test
* t
, struct test_arg ta
)
523 return add_test_arg(t
, ta
, false);
531 for(i
= 0; i
< num_tests
; i
++) {
532 for(j
= 0; j
< tests
[i
].num_args_in
; j
++) {
533 free(tests
[i
].args_in
[j
].value
);
535 free(tests
[i
].args_in
);
536 for(j
= 0; j
< tests
[i
].num_args_out
; j
++) {
537 free(tests
[i
].args_out
[j
].value
);
539 free(tests
[i
].args_out
);
544 unsigned int num_dynamic_strs
= 0;
545 char** dynamic_strs
= NULL
;
548 add_dynamic_str(char* str
)
550 add_dynamic_array((void**)&dynamic_strs
, &num_dynamic_strs
, sizeof(char*), &str
);
554 add_dynamic_str_copy(const char* src
)
556 char* dst
= malloc((strlen(src
)+1) * sizeof(char));
559 add_dynamic_str(dst
);
567 if(dynamic_strs
!= NULL
) {
570 for(i
= 0; i
< num_dynamic_strs
; i
++) {
571 free(dynamic_strs
[i
]);
581 clean(const int argc
,
583 const struct piglit_cl_program_test_config
* config
)
590 exit_report_result(enum piglit_result result
)
594 piglit_report_result(result
);
597 /* Regex functions */
600 regex_get_matches(const char* src
,
610 errcode
= regcomp(&r
, pattern
, REG_EXTENDED
| cflags
);
612 fprintf(stderr
, "Invalid regular expression: '%s'\n", pattern
);
616 /* Match regex and if pmatch != NULL && size > 0 return matched */
617 if(pmatch
== NULL
|| size
== 0) {
618 errcode
= regexec(&r
, src
, 0, NULL
, 0);
620 errcode
= regexec(&r
, src
, size
, pmatch
, 0);
629 regex_get_match_str(char** dst
,
634 size_t size
= pmatch
[index
].rm_eo
- pmatch
[index
].rm_so
;
637 *dst
= malloc((size
+1) * sizeof(char));
638 strncpy(*dst
, src
+pmatch
[index
].rm_so
, size
);
648 regex_get_str(char** dst
,
654 regmatch_t
*pmatch
= calloc(index
+1, sizeof(*pmatch
));
657 if(regex_get_matches(src
, pattern
, pmatch
, index
+1, cflags
)) {
658 ret
= regex_get_match_str(dst
, src
, pmatch
, index
);
666 regex_match(const char* src
, const char* pattern
)
668 return regex_get_matches(src
, pattern
, NULL
, 0, REG_NEWLINE
);
672 regex_section(const char* src
, char** section
)
674 regmatch_t pmatch
[2];
676 if(regex_get_matches(src
, REGEX_SECTION
, pmatch
, 2, REG_NEWLINE
)) {
677 return regex_get_match_str(section
, src
, pmatch
, 1);
684 regex_key_value(const char* src
, char** key
, char** value
)
686 regmatch_t pmatch
[3];
688 if(regex_get_matches(src
, REGEX_KEY_VALUE
, pmatch
, 3, REG_NEWLINE
)) {
691 if( regex_get_match_str(key
, src
, pmatch
, 1)
692 && regex_get_match_str(value
, src
, pmatch
, 2)) {
704 get_bool(const char* src
)
706 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_BOOL_TRUE
))) {
708 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_BOOL_FALSE
))) {
712 "Invalid configuration, could not convert to bool: %s\n",
714 exit_report_result(PIGLIT_WARN
);
720 get_int(const char* src
)
722 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_UINT
))) {
723 return strtoull(src
, NULL
, 0);
724 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_INT
))) {
725 return strtoll(src
, NULL
, 0);
728 "Invalid configuration, could not convert to long: %s\n",
730 exit_report_result(PIGLIT_WARN
);
736 get_uint(const char* src
)
738 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_UINT
))) {
739 return strtoull(src
, NULL
, 0);
742 "Invalid configuration, could not convert to ulong: %s\n",
744 exit_report_result(PIGLIT_WARN
);
750 get_float(const char* src
)
752 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_FLOAT
))) {
753 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_PNAN
))) {
755 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_NNAN
))) {
757 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_PINF
))) {
759 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_NINF
))) {
762 return strtod(src
, NULL
);
766 "Invalid configuration, could not convert to double: %s\n",
768 exit_report_result(PIGLIT_WARN
);
774 get_array_length(const char* src
)
778 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_ARRAY
))) {
779 regmatch_t pmatch
[1];
781 while(regex_get_matches(src
,
782 REGEX_ARRAY_VALUE REGEX_ARRAY_DELIMITER
,
786 src
+= pmatch
[0].rm_eo
;
789 if(regex_match(src
, REGEX_ARRAY_VALUE
)) {
794 "Invalid configuration, could not convert to an array: %s\n",
796 exit_report_result(PIGLIT_WARN
);
803 get_array(const char* src
, void** array
, size_t size
, char* array_pattern
)
811 regmatch_t pmatch
[2];
813 actual_size
= get_array_length(src
);
815 if(!strcmp(array_pattern
, REGEX_BOOL_ARRAY
)) {
817 value_pattern
= REGEX_BOOL REGEX_ARRAY_DELIMITER
;
818 *(bool**)array
= malloc(actual_size
* sizeof(bool));
819 regex_matched
= regex_match(src
, REGEX_FULL_MATCH(REGEX_BOOL_ARRAY
));
820 } else if(!strcmp(array_pattern
, REGEX_INT_ARRAY
)) {
822 value_pattern
= REGEX_INT REGEX_ARRAY_DELIMITER
;
823 *(int64_t**)array
= malloc(actual_size
* sizeof(int64_t));
824 regex_matched
= regex_match(src
, REGEX_FULL_MATCH(REGEX_INT_ARRAY
));
825 } else if(!strcmp(array_pattern
, REGEX_UINT_ARRAY
)) {
827 value_pattern
= REGEX_UINT REGEX_ARRAY_DELIMITER
;
828 *(uint64_t**)array
= malloc(actual_size
* sizeof(uint64_t));
829 regex_matched
= regex_match(src
, REGEX_FULL_MATCH(REGEX_UINT_ARRAY
));
830 } else if(!strcmp(array_pattern
, REGEX_FLOAT_ARRAY
)) {
832 value_pattern
= REGEX_FLOAT REGEX_ARRAY_DELIMITER
;
833 *(double**)array
= malloc(actual_size
* sizeof(double));
834 regex_matched
= regex_match(src
, REGEX_FULL_MATCH(REGEX_FLOAT_ARRAY
));
837 "Internal error, invalid array pattern: %s\n",
839 exit_report_result(PIGLIT_WARN
);
842 if(size
> 0 && actual_size
!= size
) {
844 "Invalid configuration, could not convert %s[%zu] to %s[%zu]: %s\n",
845 type
, actual_size
, type
, size
, src
);
846 exit_report_result(PIGLIT_WARN
);
849 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_NULL
))) {
857 "Invalid configuration, could not convert to %s array: %s\n",
859 exit_report_result(PIGLIT_WARN
);
862 while(regex_get_matches(src
, value_pattern
, pmatch
, 2, 0)) {
863 if(regex_get_match_str(&value
, src
, pmatch
, 1)) {
864 if(!strcmp(array_pattern
, REGEX_BOOL_ARRAY
)) {
865 (*(bool**)array
)[i
] = get_bool(value
);
866 } else if(!strcmp(array_pattern
, REGEX_INT_ARRAY
)) {
867 (*(int64_t**)array
)[i
] = get_int(value
);
868 } else if(!strcmp(array_pattern
, REGEX_UINT_ARRAY
)) {
869 (*(uint64_t**)array
)[i
] = get_uint(value
);
870 } else if(!strcmp(array_pattern
, REGEX_FLOAT_ARRAY
)) {
871 (*(double**)array
)[i
] = get_float(value
);
876 "Invalid configuration, could not read %s on index %zu: %s\n",
878 exit_report_result(PIGLIT_WARN
);
881 src
+= pmatch
[0].rm_eo
;
885 if(!strcmp(array_pattern
, REGEX_BOOL_ARRAY
)) {
886 (*(bool**)array
)[i
] = get_bool(src
);
887 } else if(!strcmp(array_pattern
, REGEX_INT_ARRAY
)) {
888 (*(int64_t**)array
)[i
] = get_int(src
);
889 } else if(!strcmp(array_pattern
, REGEX_UINT_ARRAY
)) {
890 (*(uint64_t**)array
)[i
] = get_uint(src
);
891 } else if(!strcmp(array_pattern
, REGEX_FLOAT_ARRAY
)) {
892 (*(double**)array
)[i
] = get_float(src
);
899 get_bool_array(const char* src
, bool** array
, size_t size
)
901 return get_array(src
, (void**)array
, size
, REGEX_BOOL_ARRAY
);
905 get_int_array(const char* src
, int64_t** array
, size_t size
)
907 return get_array(src
, (void**)array
, size
, REGEX_INT_ARRAY
);
911 get_uint_array(const char* src
, uint64_t** array
, size_t size
)
913 return get_array(src
, (void**)array
, size
, REGEX_UINT_ARRAY
);
917 get_float_array(const char* src
, double** array
, size_t size
)
919 return get_array(src
, (void**)array
, size
, REGEX_FLOAT_ARRAY
);
925 print_usage(const int argc
, const char** argv
)
928 " %s [options] CONFIG.program_test\n"
929 " %s [options] [-config CONFIG.program_test] PROGRAM.cl|PROGRAM.bin\n"
932 " - If CONFIG is not specified and PROGRAM has a comment config then a\n"
933 " comment config is used.\n"
934 " - If there is no CONFIG or comment config, then the program is only\n"
935 " tested to build properly.\n",
940 print_usage_and_warn(const int argc
, const char** argv
, const char* fmt
, ...)
944 fprintf(stderr
, "ERROR: ");
946 vfprintf(stderr
, fmt
, args
);
950 print_usage(argc
, argv
);
952 exit_report_result(PIGLIT_WARN
);
955 /* Parse configuration */
958 get_section_content(const char* src
, char** content
)
961 size_t section_name_length
= strcspn(src
, "\n\0");
962 regmatch_t pmatch
[2];
964 if(src
[section_name_length
] != '\0') {
965 src
+= section_name_length
+1;
967 src
+= section_name_length
;
970 if(regex_get_matches(src
, REGEX_SECTION
, pmatch
, 2, REG_NEWLINE
)) { // found next section
971 size
= pmatch
[1].rm_so
-1;
972 } else { // no next section
976 *content
= malloc((size
+1) * sizeof(char));
977 strncpy(*content
, src
, size
);
978 (*content
)[size
] = '\0';
984 get_test_arg_value(struct test_arg
* test_arg
, const char* value
, size_t length
)
986 size_t i
; // index in array
987 size_t c
; // component in element
988 size_t ra
; // offset from the beginning of array
989 size_t rb
; // offset from the beginning of buffer
991 int64_t* int_array
= NULL
;
992 uint64_t* uint_array
= NULL
;
993 double* float_array
= NULL
;
995 test_arg
->value
= malloc(test_arg
->size
);
998 * We fill the buffer with calculating the right offsets in the buffer (rb)
999 * and in the array (ra). Buffers of type3 have have stride of
1000 * 4*sizeof(type) while array has a stride of 3*sizeof(parsed_type).
1001 * Also the array index is inside length parameter modulo, so we can fill
1002 * the buffer with repeateable values.
1004 #define CASE(enum_type, cl_type, get_func, array) \
1006 get_func(value, &array, length); \
1007 for(i = 0; i < test_arg->length; i++) { \
1008 for(c = 0; c < test_arg->cl_size; c++) { \
1009 ra = i*test_arg->cl_size + c; \
1010 rb = i*test_arg->cl_mem_size + c; \
1011 ((cl_type*)test_arg->value)[rb] = convert_##cl_type(array[ra%length]); \
1016 switch(test_arg
->cl_type
) {
1017 CASE(TYPE_CHAR
, cl_char
, get_int_array
, int_array
)
1018 CASE(TYPE_UCHAR
, cl_uchar
, get_uint_array
, uint_array
)
1019 CASE(TYPE_SHORT
, cl_short
, get_int_array
, int_array
)
1020 CASE(TYPE_USHORT
, cl_ushort
, get_uint_array
, uint_array
)
1021 CASE(TYPE_INT
, cl_int
, get_int_array
, int_array
)
1022 CASE(TYPE_UINT
, cl_uint
, get_uint_array
, uint_array
)
1023 CASE(TYPE_LONG
, cl_long
, get_int_array
, int_array
)
1024 CASE(TYPE_ULONG
, cl_ulong
, get_uint_array
, uint_array
)
1025 CASE(TYPE_HALF
, cl_half
, get_float_array
, float_array
)
1026 CASE(TYPE_FLOAT
, cl_float
, get_float_array
, float_array
)
1027 CASE(TYPE_DOUBLE
, cl_double
, get_float_array
, float_array
)
1038 get_test_arg_tolerance(struct test_arg
* test_arg
, const char* tolerance_str
)
1040 regmatch_t pmatch
[2];
1041 char* value_str
= NULL
;
1043 if(regex_get_matches(tolerance_str
,
1044 REGEX_ARG_TOLERANCE_ULP
,
1048 regex_get_match_str(&value_str
, tolerance_str
, pmatch
, 1);
1049 switch(test_arg
->cl_type
) {
1053 test_arg
->ulp
= get_uint(value_str
);
1056 fprintf(stderr
, "ulp not value for integer types\n");
1057 exit_report_result(PIGLIT_WARN
);
1061 if(regex_get_matches(tolerance_str
,
1062 REGEX_ARG_TOLERANCE
,
1066 regex_get_match_str(&value_str
, tolerance_str
, pmatch
, 1);
1068 switch(test_arg
->cl_type
) {
1073 test_arg
->toli
= get_int(value_str
);
1079 test_arg
->tolu
= get_uint(value_str
);
1084 float value
= get_float(value_str
);
1085 test_arg
->ulp
= *((uint64_t*)(&value
));
1093 "Invalid configuration, could not parse tolerance: %s\n",
1095 exit_report_result(PIGLIT_WARN
);
1100 get_test_arg(const char* src
, struct test
* test
, bool arg_in
)
1102 regmatch_t pmatch
[5];
1103 char* index_str
= NULL
;
1106 struct test_arg test_arg
= create_test_arg();
1107 bool has_type
= true;
1110 if(regex_get_matches(src
, REGEX_FULL_MATCH(REGEX_ARG_VALUE
),
1111 pmatch
, 5, REG_NEWLINE
)) { // value
1113 } else if(regex_get_matches(src
, REGEX_FULL_MATCH(REGEX_ARG_BUFFER
),
1114 pmatch
, 5, REG_NEWLINE
)) { // buffer
1116 } else if(regex_get_matches(src
, REGEX_FULL_MATCH(REGEX_ARG_IMAGE
),
1117 pmatch
, 5, REG_NEWLINE
)) { // image
1119 } else if(regex_get_matches(src
, REGEX_FULL_MATCH(REGEX_ARG_SAMPLER
),
1120 pmatch
, 5, REG_NEWLINE
)) { // sampler
1124 "Invalid configuration, invalid test argument: %s\n",
1126 exit_report_result(PIGLIT_WARN
);
1130 regex_get_match_str(&index_str
, src
, pmatch
, 1);
1131 test_arg
.index
= get_int(index_str
);
1135 /* Set type, cl_size, cl_mem_size and size (partially for buffers) */
1136 regex_get_match_str(&type
, src
, pmatch
, 2);
1137 if(regex_match(type
, "[[:digit:]]+")) {
1138 char* type_size_str
;
1139 regex_get_str(&type_size_str
, type
, "[[:digit:]]+", 0, REG_NEWLINE
);
1140 test_arg
.cl_size
= get_int(type_size_str
);
1141 test_arg
.cl_mem_size
= test_arg
.cl_size
!= 3 ? test_arg
.cl_size
: 4; // test if we have type3
1142 free(type_size_str
);
1144 test_arg
.cl_size
= 1;
1145 test_arg
.cl_mem_size
= 1;
1148 #define IF(regex_type, enum_type, main_type) \
1149 if(regex_match(type, REGEX_FULL_MATCH(regex_type))) { \
1150 test_arg.cl_type = enum_type; \
1151 test_arg.size = sizeof(main_type) * test_arg.cl_mem_size; \
1153 #define ELSEIF(regex_type, enum_type, main_type) \
1154 else IF(regex_type, enum_type, main_type)
1156 IF (REGEX_TYPE_CHAR
, TYPE_CHAR
, cl_char
)
1157 ELSEIF(REGEX_TYPE_UCHAR
, TYPE_UCHAR
, cl_uchar
)
1158 ELSEIF(REGEX_TYPE_SHORT
, TYPE_SHORT
, cl_short
)
1159 ELSEIF(REGEX_TYPE_USHORT
, TYPE_USHORT
, cl_ushort
)
1160 ELSEIF(REGEX_TYPE_INT
, TYPE_INT
, cl_int
)
1161 ELSEIF(REGEX_TYPE_UINT
, TYPE_UINT
, cl_uint
)
1162 ELSEIF(REGEX_TYPE_LONG
, TYPE_LONG
, cl_long
)
1163 ELSEIF(REGEX_TYPE_ULONG
, TYPE_ULONG
, cl_ulong
)
1164 ELSEIF(REGEX_TYPE_HALF
, TYPE_HALF
, cl_half
)
1165 ELSEIF(REGEX_TYPE_FLOAT
, TYPE_FLOAT
, cl_float
)
1166 ELSEIF(REGEX_TYPE_DOUBLE
, TYPE_DOUBLE
, cl_double
)
1174 /* Get arg type, size and value */
1175 if(regex_match(src
, REGEX_FULL_MATCH(REGEX_ARG_VALUE
))) { // value
1176 /* Values are only allowed for in arguments */
1179 "Invalid configuration, only arg_in values are allowed: %s\n",
1181 exit_report_result(PIGLIT_WARN
);
1185 test_arg
.type
= TEST_ARG_VALUE
;
1188 test_arg
.length
= 1;
1191 regex_get_match_str(&value
, src
, pmatch
, 3);
1192 if(regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1193 test_arg
.value
= NULL
;
1195 get_test_arg_value(&test_arg
, value
, test_arg
.cl_size
);
1198 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_ARG_BUFFER
))) { // buffer
1199 char* array_length_str
= NULL
;
1200 const char* tolerance_str
= NULL
;
1203 test_arg
.type
= TEST_ARG_BUFFER
;
1206 regex_get_match_str(&array_length_str
, src
, pmatch
, 3);
1207 test_arg
.length
= get_int(array_length_str
);
1208 free(array_length_str
);
1211 test_arg
.size
= test_arg
.size
* test_arg
.length
;
1214 tolerance_str
= src
+pmatch
[4].rm_eo
;
1215 if(regex_match(tolerance_str
, REGEX_ARG_TOLERANCE
)) {
1218 "Invalid configuration, in argument buffer can't have tolerance: %s\n",
1220 exit_report_result(PIGLIT_WARN
);
1222 get_test_arg_tolerance(&test_arg
, tolerance_str
);
1226 regex_get_match_str(&value
, src
, pmatch
, 4);
1227 if(regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1228 test_arg
.value
= NULL
;
1231 "Invalid configuration, out argument buffer value can not be NULL: %s\n",
1233 exit_report_result(PIGLIT_WARN
);
1236 if(regex_match(value
, REGEX_FULL_MATCH(REGEX_RANDOM
))) {
1237 test_arg
.value
= malloc(test_arg
.size
);
1240 "Invalid configuration, out argument buffer can not be random: %s\n",
1242 exit_report_result(PIGLIT_WARN
);
1244 } else if(regex_match(value
, REGEX_FULL_MATCH(REGEX_REPEAT
))) {
1245 regmatch_t rmatch
[3];
1246 char* repeat_value_str
;
1248 regex_get_matches(value
, REGEX_REPEAT
, rmatch
, 3, 0);
1249 regex_get_match_str(&repeat_value_str
, value
, rmatch
, 2);
1251 get_test_arg_value(&test_arg
,
1253 get_array_length(repeat_value_str
));
1255 free(repeat_value_str
);
1256 } else if(regex_match(value
, REGEX_ARRAY
)) {
1257 get_test_arg_value(&test_arg
,
1259 test_arg
.length
* test_arg
.cl_size
);
1263 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_ARG_IMAGE
))) { // image
1265 const char* properties_str
= src
+ pmatch
[3].rm_eo
;
1266 const char* tolerance_str
= NULL
;
1267 size_t image_elems
= 0;
1268 cl_channel_order cho
;
1269 cl_channel_type cht
;
1270 regmatch_t pmatch_prop
[2];
1273 test_arg
.type
= TEST_ARG_IMAGE
;
1276 regex_get_matches(properties_str
, REGEX_ARG_IMAGE_TYPE
,
1277 pmatch_prop
, 2, REG_NEWLINE
);
1278 regex_get_match_str(&str
, properties_str
, pmatch_prop
, 1);
1279 properties_str
+= pmatch_prop
[1].rm_eo
;
1280 if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_IMGT_2D
")"))) {
1281 test_arg
.image_desc
.image_type
= CL_MEM_OBJECT_IMAGE2D
;
1283 /* TODO: Implement other image types */
1284 fprintf(stderr
, "Image type not supported: %s\n", str
);
1285 exit_report_result(PIGLIT_WARN
);
1290 regex_get_matches(properties_str
, REGEX_ARG_IMAGE_WIDTH
,
1291 pmatch_prop
, 2, REG_NEWLINE
);
1292 regex_get_match_str(&str
, properties_str
, pmatch_prop
, 1);
1293 properties_str
+= pmatch_prop
[1].rm_eo
;
1294 test_arg
.image_desc
.image_width
= get_int(str
);
1298 regex_get_matches(properties_str
, REGEX_ARG_IMAGE_HEIGHT
,
1299 pmatch_prop
, 2, REG_NEWLINE
);
1300 regex_get_match_str(&str
, properties_str
, pmatch_prop
, 1);
1301 properties_str
+= pmatch_prop
[1].rm_eo
;
1302 test_arg
.image_desc
.image_height
= get_int(str
);
1305 /* Image descriptor defaults */
1306 test_arg
.image_desc
.image_depth
= 1;
1307 test_arg
.image_desc
.image_array_size
= 1;
1308 test_arg
.image_desc
.image_row_pitch
= 0;
1309 test_arg
.image_desc
.image_slice_pitch
= 0;
1310 test_arg
.image_desc
.num_mip_levels
= 0;
1311 test_arg
.image_desc
.num_samples
= 0;
1312 test_arg
.image_desc
.buffer
= NULL
;
1314 /* Image channel order */
1315 regex_get_matches(properties_str
, REGEX_ARG_IMAGE_CHANNEL_ORDER
,
1316 pmatch_prop
, 2, REG_NEWLINE
);
1317 regex_get_match_str(&str
, properties_str
, pmatch_prop
, 1);
1318 properties_str
+= pmatch_prop
[1].rm_eo
;
1319 if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_R
")"))) {
1321 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RX
")"))) {
1323 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_A
")"))) {
1325 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_INTENSITY
")"))) {
1327 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_LUMINANCE
")"))) {
1329 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RG
")"))) {
1331 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RGX
")"))) {
1333 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RA
")"))) {
1335 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RGB
")"))) {
1337 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RGBX
")"))) {
1339 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_RGBA
")"))) {
1341 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_ARGB
")"))) {
1343 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHO_BGRA
")"))) {
1346 fprintf(stderr
, "Image channel order not supported: %s\n", str
);
1347 exit_report_result(PIGLIT_WARN
);
1350 test_arg
.image_format
.image_channel_order
= cho
;
1352 /* Image channel data type */
1353 regex_get_matches(properties_str
, REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE
,
1354 pmatch_prop
, 2, REG_NEWLINE
);
1355 regex_get_match_str(&str
, properties_str
, pmatch_prop
, 1);
1356 properties_str
+= pmatch_prop
[1].rm_eo
;
1357 if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_SNORM_INT8
")"))) {
1358 cht
= CL_SNORM_INT8
;
1359 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_SNORM_INT16
")"))) {
1360 cht
= CL_SNORM_INT16
;
1361 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT8
")"))) {
1362 cht
= CL_UNORM_INT8
;
1363 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT16
")"))) {
1364 cht
= CL_UNORM_INT16
;
1365 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_SHORT_565
")"))) {
1366 cht
= CL_UNORM_SHORT_565
;
1367 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_SHORT_555
")"))) {
1368 cht
= CL_UNORM_SHORT_555
;
1369 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT_101010
")"))) {
1370 cht
= CL_UNORM_INT_101010
;
1371 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT8
")"))) {
1372 cht
= CL_SIGNED_INT8
;
1373 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT16
")"))) {
1374 cht
= CL_SIGNED_INT16
;
1375 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT32
")"))) {
1376 cht
= CL_SIGNED_INT32
;
1377 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT8
")"))) {
1378 cht
= CL_UNSIGNED_INT8
;
1379 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT16
")"))) {
1380 cht
= CL_UNSIGNED_INT16
;
1381 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT32
")"))) {
1382 cht
= CL_UNSIGNED_INT32
;
1383 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_HALF_FLOAT
")"))) {
1384 cht
= CL_HALF_FLOAT
;
1385 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_CHT_FLOAT
")"))) {
1388 fprintf(stderr
, "Image channel data type not supported: %s\n", str
);
1389 exit_report_result(PIGLIT_WARN
);
1392 test_arg
.image_format
.image_channel_data_type
= cht
;
1395 image_elems
= test_arg
.image_desc
.image_width
*
1396 test_arg
.image_desc
.image_height
*
1397 test_arg
.image_desc
.image_depth
*
1398 test_arg
.image_desc
.image_array_size
;
1399 test_arg
.length
= image_elems
;
1400 test_arg
.size
*= image_elems
;
1403 tolerance_str
= properties_str
;
1404 if(regex_match(tolerance_str
, REGEX_ARG_TOLERANCE
)) {
1407 "Invalid configuration, in argument buffer can't have tolerance: %s\n",
1409 exit_report_result(PIGLIT_WARN
);
1411 get_test_arg_tolerance(&test_arg
, tolerance_str
);
1415 regex_get_match_str(&value
, src
, pmatch
, 3);
1416 if(regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1417 test_arg
.value
= NULL
;
1420 "Invalid configuration, out argument buffer value can not be NULL: %s\n",
1422 exit_report_result(PIGLIT_WARN
);
1425 if(regex_match(value
, REGEX_FULL_MATCH(REGEX_RANDOM
))) {
1426 test_arg
.value
= malloc(test_arg
.size
);
1429 "Invalid configuration, out argument buffer can not be random: %s\n",
1431 exit_report_result(PIGLIT_WARN
);
1433 } else if(regex_match(value
, REGEX_FULL_MATCH(REGEX_REPEAT
))) {
1434 regmatch_t rmatch
[3];
1435 char* repeat_value_str
;
1437 regex_get_matches(value
, REGEX_REPEAT
, rmatch
, 3, 0);
1438 regex_get_match_str(&repeat_value_str
, value
, rmatch
, 2);
1440 get_test_arg_value(&test_arg
,
1442 get_array_length(repeat_value_str
));
1444 free(repeat_value_str
);
1445 } else if(regex_match(value
, REGEX_ARRAY
)) {
1446 get_test_arg_value(&test_arg
, value
,
1447 image_elems
* test_arg
.cl_size
);
1452 } else if(regex_match(src
, REGEX_FULL_MATCH(REGEX_ARG_SAMPLER
))) { // sampler
1455 /* Samplers are only allowed for in arguments */
1458 "Invalid configuration, only arg_in samplers are allowed: %s\n",
1460 exit_report_result(PIGLIT_WARN
);
1463 test_arg
.size
= sizeof(cl_sampler
);
1466 test_arg
.type
= TEST_ARG_SAMPLER
;
1468 /* Normalized coords */
1469 regex_get_match_str(&str
, src
, pmatch
, 2);
1470 test_arg
.sampler_normalized_coords
= get_bool(str
);
1473 /* Addressing mode */
1474 regex_get_match_str(&str
, src
, pmatch
, 3);
1475 if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_NONE
")"))) {
1476 test_arg
.sampler_addressing_mode
= CL_ADDRESS_NONE
;
1477 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_CLAMP_TO_EDGE
")"))) {
1478 test_arg
.sampler_addressing_mode
= CL_ADDRESS_CLAMP_TO_EDGE
;
1479 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_CLAMP
")"))) {
1480 test_arg
.sampler_addressing_mode
= CL_ADDRESS_CLAMP
;
1481 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_REPEAT
))) {
1482 test_arg
.sampler_addressing_mode
= CL_ADDRESS_REPEAT
;
1483 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_MIRRORED_REPEAT
))) {
1484 test_arg
.sampler_addressing_mode
= CL_ADDRESS_MIRRORED_REPEAT
;
1486 fprintf(stderr
, "Sampler addressing mode not supported: %s\n", str
);
1487 exit_report_result(PIGLIT_WARN
);
1492 regex_get_match_str(&str
, src
, pmatch
, 4);
1493 if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_FILT_NEAREST
")"))) {
1494 test_arg
.sampler_filter_mode
= CL_FILTER_NEAREST
;
1495 } else if(regex_match(str
, REGEX_FULL_MATCH("("REGEX_SAMP_FILT_LINEAR
")"))) {
1496 test_arg
.sampler_filter_mode
= CL_FILTER_LINEAR
;
1498 fprintf(stderr
, "Sampler filter mode not supported: %s\n", str
);
1499 exit_report_result(PIGLIT_WARN
);
1505 if(!add_test_arg_in(test
, test_arg
)) {
1507 "Invalid configuration, could not add in argument: %s\n",
1509 exit_report_result(PIGLIT_WARN
);
1512 if(!add_test_arg_out(test
, test_arg
)) {
1514 "Invalid configuration, could not add out argument: %s\n",
1516 exit_report_result(PIGLIT_WARN
);
1522 * Helper function for parsing a test name and checking for illegal characters.
1525 parse_name(const char *input
)
1527 char *name
= add_dynamic_str_copy(input
);
1530 regmatch_t pmatch
[1];
1533 if ((error
= regcomp(®ex
, "\\([/%]\\)",0))) {
1535 regerror(error
, ®ex
, errbuf
, 100);
1536 fprintf(stderr
, "Failed to compile regex for parse_name():%s\n", errbuf
);
1540 if (!regexec(®ex
, input
, 1, pmatch
, 0)) {
1541 char bad_char
= *(input
+ pmatch
[0].rm_so
);
1542 fprintf(stderr
, "Illegal character in test name '%s': %c\n",
1552 parse_config(const char* config_str
,
1553 struct piglit_cl_program_test_config
* config
)
1556 size_t length
= strlen(config_str
);
1559 char* section
= NULL
;
1563 struct test
* test
= NULL
;
1565 bool config_found
= false;
1566 bool test_found
= false;
1572 } state
= SECTION_NONE
;
1574 /* parse config string by each line */
1576 while(pch
< (config_str
+length
)) {
1577 regmatch_t pmatch
[2];
1581 regex_get_matches(pch
, REGEX_LINE
, pmatch
, 2, REG_NEWLINE
);
1582 line_length
= pmatch
[0].rm_eo
- pmatch
[0].rm_so
;
1583 if(!regex_get_match_str(&line
, pch
, pmatch
, 1)) {
1585 pch
+= line_length
+ 1;
1589 /* Get more lines if it is a multiline */
1590 if( regex_match(line
, REGEX_KEY_VALUE
)
1591 && regex_match(line
, REGEX_MULTILINE
)) {
1592 char* multiline
= malloc(sizeof(char));
1593 multiline
[0] = '\0';
1595 free(line
); line
= NULL
;
1597 while((pch
<= (config_str
+length
))) {
1598 regmatch_t mmatch
[2];
1599 char* old_multiline
= multiline
;
1600 char* new_multiline
;
1603 regex_get_matches(pch
, REGEX_LINE
, pmatch
, 2, REG_NEWLINE
);
1604 line_length
= pmatch
[0].rm_eo
- pmatch
[0].rm_so
;
1605 if(!regex_get_match_str(&line
, pch
, pmatch
, 1)) {
1610 if(regex_match(line
, REGEX_MULTILINE
)) { // not last line
1611 regex_get_matches(line
, REGEX_MULTILINE
,
1612 mmatch
, 2, REG_NEWLINE
);
1613 if(!regex_get_match_str(&new_multiline
, pch
, mmatch
, 1)) {
1614 /* Multiline is empty */
1615 pch
+= line_length
+ 1;
1619 multiline
= malloc(strlen(old_multiline
) + strlen(new_multiline
) + 1);
1620 strncpy(multiline
, old_multiline
, strlen(old_multiline
));
1621 strcpy(multiline
+strlen(old_multiline
), new_multiline
);
1623 pch
+= line_length
+1;
1625 free(line
); free(old_multiline
); free(new_multiline
);
1626 } else { // last line
1627 multiline
= malloc(strlen(old_multiline
) + strlen(line
) + 1);
1628 strncpy(multiline
, old_multiline
, strlen(old_multiline
));
1629 strcpy(multiline
+strlen(old_multiline
), line
);
1631 free(line
); free(old_multiline
);
1640 if(regex_section(line
, §ion
)) { // SECTION
1641 if(regex_match(section
, "^config$")) { // config
1643 fprintf(stderr
, "Invalid configuration, [config] section can be defined only once\n");
1644 free(section
); section
= NULL
;
1645 exit_report_result(PIGLIT_WARN
);
1648 fprintf(stderr
, "Invalid configuration, [config] section must be declared before any [test] section\n");
1649 free(section
); section
= NULL
;
1650 exit_report_result(PIGLIT_WARN
);
1652 config_found
= true;
1653 state
= SECTION_CONFIG
;
1654 } else if(regex_match(section
, "^test$")) { // test
1656 fprintf(stderr
, "Invalid configuration, [config] section must be declared before any [test] section\n");
1657 free(section
); section
= NULL
;
1658 exit_report_result(PIGLIT_WARN
);
1660 if(config
->expect_build_fail
) {
1661 fprintf(stderr
, "Invalid configuration, no tests can be defined when expect_build_fail is true\n");
1662 free(section
); section
= NULL
;
1663 exit_report_result(PIGLIT_WARN
);
1666 add_test(create_test());
1667 test
= &tests
[num_tests
-1];
1668 state
= SECTION_TEST
;
1669 } else if(regex_match(section
, "^program source$")) { // program source
1670 pch
+= get_section_content(pch
, &config
->program_source
);
1671 add_dynamic_str(config
->program_source
);
1672 state
= SECTION_NONE
;
1673 } else if(regex_match(section
, "^program binary$")) { // program binary
1674 pch
+= get_section_content(pch
, (char**)&config
->program_binary
);
1675 add_dynamic_str((char*)config
->program_binary
);
1676 state
= SECTION_NONE
;
1679 "Invalid configuration, configuration has an invalid section: [%s]\n",
1681 free(section
); section
= NULL
;
1682 exit_report_result(PIGLIT_WARN
);
1685 free(section
); section
= NULL
;
1686 } else if(regex_key_value(line
, &key
, &value
)) { // KEY : VALUE
1690 "Invalid configuration, this key-value does not belong to any section: %s\n",
1692 free(key
); key
= NULL
;
1693 free(value
); value
= NULL
;
1694 exit_report_result(PIGLIT_WARN
);
1696 case SECTION_CONFIG
:
1697 if(regex_match(key
, "^name$")) {
1698 config
->name
= parse_name(value
);
1699 if (!config
->name
) {
1700 exit_report_result(PIGLIT_FAIL
);
1702 } else if(regex_match(key
, "^clc_version_min$")) {
1703 config
->clc_version_min
= get_int(value
);
1704 } else if(regex_match(key
, "clc_version_max$")) {
1705 config
->clc_version_max
= get_int(value
);
1706 } else if(regex_match(key
, "^platform_regex$")) {
1707 config
->platform_regex
= add_dynamic_str_copy(value
);
1708 } else if(regex_match(key
, "^device_regex$")) {
1709 config
->device_regex
= add_dynamic_str_copy(value
);
1710 } else if(regex_match(key
, "^require_platform_extensions$")) {
1711 config
->require_platform_extensions
=
1712 add_dynamic_str_copy(value
);
1713 } else if(regex_match(key
, "^require_device_extensions$")) {
1714 config
->require_device_extensions
=
1715 add_dynamic_str_copy(value
);
1716 } else if(regex_match(key
, "^program_source_file$")) {
1717 config
->program_source_file
= add_dynamic_str_copy(value
);
1718 } else if(regex_match(key
, "^program_binary_file$")) {
1719 config
->program_binary_file
= add_dynamic_str_copy(value
);
1720 } else if(regex_match(key
, "^build_options$")) {
1721 config
->build_options
= add_dynamic_str_copy(value
);
1722 } else if(regex_match(key
, "^kernel_name$")) {
1723 if(!regex_match(value
, REGEX_NULL
)) {
1724 config
->kernel_name
= add_dynamic_str_copy(value
);
1726 config
->kernel_name
= NULL
;
1728 } else if(regex_match(key
, "^expect_build_fail$")) {
1729 config
->expect_build_fail
= get_bool(value
);
1730 } else if(regex_match(key
, "^expect_test_fail$")) {
1731 expect_test_fail
= get_bool(value
);
1732 } else if(regex_match(key
, "^need_image_support$")) {
1733 config
->need_image_support
= get_bool(value
);
1734 } else if(regex_match(key
, "^dimensions$")) {
1735 work_dimensions
= get_uint(value
);
1736 } else if(regex_match(key
, "^global_size$")) {
1738 uint64_t* int_global_work_size
;
1739 get_uint_array(value
, &int_global_work_size
, 3);
1740 for(i
= 0; i
< 3; i
++) {
1741 global_work_size
[i
] = int_global_work_size
[i
];
1743 free(int_global_work_size
);
1744 } else if(regex_match(key
, "^local_size$")) {
1745 if(!regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1747 uint64_t* int_local_work_size
;
1748 get_uint_array(value
, &int_local_work_size
, 3);
1749 for(i
= 0; i
< 3; i
++) {
1750 local_work_size
[i
] = int_local_work_size
[i
];
1752 local_work_size_null
= false;
1753 free(int_local_work_size
);
1755 local_work_size_null
= true;
1757 } else if(regex_match(key
, "^global_offset$")) {
1758 if(!regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1760 uint64_t* int_global_offset
;
1761 get_uint_array(value
, &int_global_offset
, 3);
1762 for(i
= 0; i
< 3; i
++) {
1763 global_offset
[i
] = int_global_offset
[i
];
1765 global_offset_null
= false;
1766 free(int_global_offset
);
1768 global_offset_null
= true;
1772 "Invalid configuration, key '%s' does not belong to a [config] section: %s\n",
1774 free(key
); key
= NULL
;
1775 free(value
); value
= NULL
;
1776 exit_report_result(PIGLIT_WARN
);
1780 if(regex_match(key
, "^name$")) {
1781 test
->name
= parse_name(value
);
1783 exit_report_result(PIGLIT_FAIL
);
1785 } else if(regex_match(key
, "^kernel_name$")) {
1786 test
->kernel_name
= add_dynamic_str_copy(value
); // test can't have kernel_name == NULL like config section
1787 } else if(regex_match(key
, "^expect_test_fail$")) {
1788 test
->expect_test_fail
= get_bool(value
);
1789 } else if(regex_match(key
, "^dimensions$")) {
1790 test
->work_dimensions
= get_uint(value
);
1791 } else if(regex_match(key
, "^global_size$")) {
1793 uint64_t* int_global_work_size
;
1794 get_uint_array(value
, &int_global_work_size
, 3);
1795 for(i
= 0; i
< 3; i
++) {
1796 test
->global_work_size
[i
] = int_global_work_size
[i
];
1798 free(int_global_work_size
);
1799 } else if(regex_match(key
, "^local_size$")) {
1800 if(!regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1802 uint64_t* int_local_work_size
;
1803 get_uint_array(value
, &int_local_work_size
, 3);
1804 for(i
= 0; i
< 3; i
++) {
1805 test
->local_work_size
[i
] = int_local_work_size
[i
];
1807 test
->local_work_size_null
= false;
1808 free(int_local_work_size
);
1810 test
->local_work_size_null
= true;
1812 } else if(regex_match(key
, "^global_offset$")) {
1813 if(!regex_match(value
, REGEX_FULL_MATCH(REGEX_NULL
))) {
1815 uint64_t* int_global_offset
;
1816 get_uint_array(value
, &int_global_offset
, 3);
1817 for(i
= 0; i
< 3; i
++) {
1818 test
->global_offset
[i
] = int_global_offset
[i
];
1820 test
->global_offset_null
= false;
1821 free(int_global_offset
);
1823 test
->global_offset_null
= true;
1825 } else if(regex_match(key
, "^arg_in$")) {
1826 get_test_arg(value
, test
, true);
1827 } else if(regex_match(key
, "^arg_out$")) {
1828 get_test_arg(value
, test
, false);
1831 "Invalid configuration, key '%s' does not belong to a [test] section: %s\n",
1833 free(key
); key
= NULL
;
1834 free(value
); value
= NULL
;
1835 exit_report_result(PIGLIT_WARN
);
1840 free(key
); key
= NULL
;
1841 free(value
); value
= NULL
;
1842 } else if(!regex_match(line
, REGEX_IGNORE
)){ // not WHITESPACE or COMMENT
1844 "Invalid configuration, configuration could not be parsed: %s\n",
1846 exit_report_result(PIGLIT_WARN
);
1849 /* Go to next line */
1850 free(line
); line
= NULL
;
1851 pch
+= line_length
+1;
1855 fprintf(stderr
, "Invalid configuration, configuration is missing a [config] section.\n");
1856 exit_report_result(PIGLIT_WARN
);
1860 /* Get configuration from comment */
1863 get_comment_config_str(const char* src
)
1865 char* config_str
= NULL
;
1866 regmatch_t pmatch
[2];
1868 if(regex_get_matches(src
, REGEX_COMMENT_CONFIG
, pmatch
, 2, 0)) {
1869 if(regex_get_match_str(&config_str
, src
, pmatch
, 1)) {
1880 init(const int argc
,
1882 struct piglit_cl_program_test_config
* config
)
1884 const char * main_argument
= piglit_cl_get_unnamed_arg(argc
, argv
, 0);
1885 const char * config_file
= NULL
;
1887 char* config_str
= NULL
;
1888 unsigned int config_str_size
;
1889 bool config_arg_present
= piglit_cl_is_arg_defined(argc
, argv
, "config");
1891 enum main_argument_type_t
{
1895 } main_argument_type
;
1899 int program_count
= 0;
1901 /* Check if arguments are valid */
1902 // valid main argument
1903 if(main_argument
== NULL
) {
1905 print_usage(argc
, argv
);
1906 exit_report_result(PIGLIT_WARN
);
1908 print_usage_and_warn(argc
, argv
, "No main argument.");
1911 if(!regex_match(main_argument
, "\\.(cl|program_test|bin)$")) {
1912 print_usage_and_warn(argc
, argv
, "Invalid main argument.");
1914 temp_file
= fopen(main_argument
, "r");
1915 if(temp_file
== NULL
) {
1916 print_usage_and_warn(argc
, argv
, "%s does not exist.", main_argument
);
1919 // valid config argument
1920 if(config_arg_present
) {
1921 config_file
= piglit_cl_get_arg_value(argc
, argv
, "config");
1922 if(!regex_match(config_file
, "\\.program_test$")) {
1923 print_usage_and_warn(argc
, argv
, "Invalid config argument.");
1925 temp_file
= fopen(config_file
, "r");
1926 if(temp_file
== NULL
) {
1927 print_usage_and_warn(argc
, argv
, "%s does not exist.", config_file
);
1931 // no config argument if using .program_test
1932 if(regex_match(main_argument
, "\\.program_test$") && config_arg_present
) {
1933 print_usage_and_warn(argc
,
1935 "Cannot use config argument if main argument is already a config file.");
1938 /* Get main_argument type and config string */
1939 if(regex_match(main_argument
, "\\.program_test$")) {
1940 main_argument_type
= ARG_CONFIG
;
1942 config_file
= main_argument
;
1943 config_str
= piglit_load_text_file(config_file
, &config_str_size
);
1944 } else if(regex_match(main_argument
, "\\.cl$")) {
1945 main_argument_type
= ARG_SOURCE
;
1947 if(config_arg_present
) {
1948 config_file
= piglit_cl_get_arg_value(argc
, argv
, "config");
1949 config_str
= piglit_load_text_file(config_file
, &config_str_size
);
1953 config_file
= main_argument
;
1954 source_str
= piglit_load_text_file(config_file
, &config_str_size
);
1955 config_str
= get_comment_config_str(source_str
);
1959 } else if(regex_match(main_argument
, "\\.bin$")) {
1960 main_argument_type
= ARG_BINARY
;
1962 config_file
= piglit_cl_get_arg_value(argc
, argv
, "config");
1963 config_str
= piglit_load_text_file(config_file
, &config_str_size
);
1965 fprintf(stderr
, "Ops, this should not happen!\n");
1966 exit_report_result(PIGLIT_WARN
);
1969 /* Parse test configuration */
1970 if(config_str
!= NULL
) {
1971 parse_config(config_str
, config
);
1974 fprintf(stderr
, "No configuration found.\n");
1978 switch(main_argument_type
) {
1980 if( config
->program_source_file
!= NULL
1981 || config
->program_binary_file
!= NULL
) {
1982 const char* program_file
= NULL
;
1983 char* main_arg_copy
= NULL
;
1985 char* full_path_file
= NULL
;
1987 if(config
->program_source_file
!= NULL
) {
1988 program_file
= config
->program_source_file
;
1990 program_file
= config
->program_binary_file
;
1993 main_arg_copy
= strdup(main_argument
);
1994 dname
= dirname(main_arg_copy
);
1995 full_path_file
= malloc(strlen(dname
) + strlen(program_file
) + 2); // +2 for '/' and '\0'
1996 strcpy(full_path_file
, dname
);
1997 full_path_file
[strlen(dname
)] = '/';
1998 strcpy(full_path_file
+strlen(dname
)+1, program_file
);
2000 if(config
->program_source_file
!= NULL
) {
2001 config
->program_source_file
= full_path_file
;
2003 config
->program_binary_file
= full_path_file
;
2006 add_dynamic_str(full_path_file
);
2007 free(main_arg_copy
);
2011 config
->program_source_file
= add_dynamic_str_copy(main_argument
);
2014 config
->program_binary_file
= add_dynamic_str_copy(main_argument
);
2018 /* Check if there is one program_* set */
2019 if(config
->program_source
!= NULL
) program_count
++;
2020 if(config
->program_source_file
!= NULL
) program_count
++;
2021 if(config
->program_binary
!= NULL
) program_count
++;
2022 if(config
->program_binary_file
!= NULL
) program_count
++;
2023 if(program_count
== 0) {
2024 fprintf(stderr
, "Invalid configuration, no program defined.\n");
2025 exit_report_result(PIGLIT_WARN
);
2026 } else if (program_count
> 1) {
2027 fprintf(stderr
, "Invalid configuration, multiple programs defined.\n");
2028 exit_report_result(PIGLIT_WARN
);
2031 /* Run test per device */
2032 config
->run_per_device
= true;
2035 /* Memory object functions */
2040 cl_mem_object_type type
;
2044 free_mem_args(struct mem_arg
** mem_args
, unsigned int* num_mem_args
)
2048 for(i
= 0; i
< *num_mem_args
; i
++) {
2049 clReleaseMemObject((*mem_args
)[i
].mem
);
2052 free(*mem_args
); *mem_args
= NULL
;
2057 free_sampler_args(cl_sampler
** sampler_args
, unsigned int* num_sampler_args
)
2061 for(i
= 0; i
< *num_sampler_args
; i
++) {
2062 clReleaseSampler((*sampler_args
)[i
]);
2065 free(*sampler_args
); *sampler_args
= NULL
;
2066 *num_sampler_args
= 0;
2070 check_test_arg_value(struct test_arg test_arg
,
2073 size_t i
; // index in array
2074 size_t c
; // component in element
2075 size_t ra
; // offset from the beginning of parsed array
2076 size_t rb
; // offset from the beginning of buffer
2078 #define CASEI(enum_type, type, cl_type) \
2080 for(i = 0; i < test_arg.length; i++) { \
2081 for(c = 0; c < test_arg.cl_size; c++) { \
2082 rb = i*test_arg.cl_mem_size + c; \
2083 if(!piglit_cl_probe_integer(((cl_type*)value)[rb], \
2084 ((cl_type*)test_arg.value)[rb], \
2086 ra = i*test_arg.cl_size + c; \
2087 printf("Error at %s[%zu]\n", type, ra); \
2093 #define CASEU(enum_type, type, cl_type) \
2095 for(i = 0; i < test_arg.length; i++) { \
2096 for(c = 0; c < test_arg.cl_size; c++) { \
2097 rb = i*test_arg.cl_mem_size + c; \
2098 if(!piglit_cl_probe_uinteger(((cl_type*)value)[rb], \
2099 ((cl_type*)test_arg.value)[rb], \
2101 ra = i*test_arg.cl_size + c; \
2102 printf("Error at %s[%zu]\n", type, ra); \
2108 #define CASEH(enum_type, type, cl_type) \
2110 for(i = 0; i < test_arg.length; i++) { \
2111 for(c = 0; c < test_arg.cl_size; c++) { \
2112 rb = i*test_arg.cl_mem_size + c; \
2113 if(!piglit_cl_probe_half(((cl_type*)value)[rb], \
2114 ((cl_type*)test_arg.value)[rb], \
2116 ra = i*test_arg.cl_size + c; \
2117 printf("Error at %s[%zu]\n", type, ra); \
2123 #define CASEF(enum_type, type, cl_type, testfn) \
2125 for(i = 0; i < test_arg.length; i++) { \
2126 for(c = 0; c < test_arg.cl_size; c++) { \
2127 rb = i*test_arg.cl_mem_size + c; \
2128 if(!testfn(((cl_type*)value)[rb], \
2129 ((cl_type*)test_arg.value)[rb], \
2131 ra = i*test_arg.cl_size + c; \
2132 printf("Error at %s[%zu]\n", type, ra); \
2139 switch(test_arg
.cl_type
) {
2140 CASEI(TYPE_CHAR
, "char", cl_char
)
2141 CASEU(TYPE_UCHAR
, "uchar", cl_uchar
)
2142 CASEI(TYPE_SHORT
, "short", cl_short
)
2143 CASEU(TYPE_USHORT
, "ushort", cl_ushort
)
2144 CASEI(TYPE_INT
, "int", cl_int
)
2145 CASEU(TYPE_UINT
, "uint", cl_uint
)
2146 CASEI(TYPE_LONG
, "long", cl_long
)
2147 CASEU(TYPE_ULONG
, "ulong", cl_ulong
)
2148 CASEH(TYPE_HALF
, "half", cl_half
)
2149 CASEF(TYPE_FLOAT
, "float", cl_float
, piglit_cl_probe_floating
)
2150 CASEF(TYPE_DOUBLE
, "double", cl_double
, piglit_cl_probe_double
)
2160 /* Run the kernel test */
2162 test_kernel(const struct piglit_cl_program_test_config
* config
,
2163 const struct piglit_cl_program_test_env
* env
,
2166 enum piglit_result result
= PIGLIT_PASS
;
2173 // setting/validating arguments
2174 struct mem_arg
* mem_args
= NULL
;
2175 unsigned int num_mem_args
= 0;
2177 cl_sampler
*sampler_args
= NULL
;
2178 unsigned int num_sampler_args
= 0;
2180 /* Check if this device supports the local work size. */
2181 if (!piglit_cl_framework_check_local_work_size(env
->device_id
,
2182 test
.local_work_size
)) {
2186 /* Create or use appropriate kernel */
2187 if(test
.kernel_name
== NULL
) {
2188 kernel_name
= config
->kernel_name
;
2189 kernel
= env
->kernel
;
2191 if(config
->kernel_name
== NULL
) {
2192 printf("No kernel_name defined\n");
2195 clRetainKernel(kernel
);
2198 kernel_name
= test
.kernel_name
;
2199 kernel
= piglit_cl_create_kernel(env
->program
, test
.kernel_name
);
2201 if(kernel
== NULL
) {
2202 printf("Could not create kernel %s\n", kernel_name
);
2207 printf("Using kernel %s\n", kernel_name
);
2209 /* Set kernel args */
2210 printf("Setting kernel arguments...\n");
2212 for(j
= 0; j
< test
.num_args_in
; j
++) {
2213 bool arg_set
= false;
2214 struct test_arg test_arg
= test
.args_in
[j
];
2216 switch(test_arg
.type
) {
2217 case TEST_ARG_VALUE
:
2218 arg_set
= piglit_cl_set_kernel_arg(kernel
,
2223 case TEST_ARG_BUFFER
: {
2224 struct mem_arg mem_arg
;
2225 mem_arg
.index
= test_arg
.index
;
2226 mem_arg
.type
= CL_MEM_OBJECT_BUFFER
;
2228 if(test_arg
.value
!= NULL
) {
2229 mem_arg
.mem
= piglit_cl_create_buffer(env
->context
,
2232 if( mem_arg
.mem
!= NULL
2233 && piglit_cl_write_buffer(env
->context
->command_queues
[0],
2238 && piglit_cl_set_kernel_arg(kernel
,
2246 arg_set
= piglit_cl_set_kernel_arg(kernel
,
2253 add_dynamic_array((void**)&mem_args
,
2255 sizeof(struct mem_arg
),
2260 case TEST_ARG_IMAGE
: {
2261 struct mem_arg mem_arg
;
2262 mem_arg
.index
= test_arg
.index
;
2263 mem_arg
.type
= test_arg
.image_desc
.image_type
;
2265 if(!test_arg
.value
) {
2266 printf("Image argument cannot be null.\n");
2271 mem_arg
.mem
= piglit_cl_create_image(env
->context
,
2273 &test_arg
.image_format
,
2274 &test_arg
.image_desc
);
2275 if( mem_arg
.mem
!= NULL
2276 && piglit_cl_write_whole_image(env
->context
->command_queues
[0],
2279 && piglit_cl_set_kernel_arg(kernel
,
2287 add_dynamic_array((void**)&mem_args
,
2289 sizeof(struct mem_arg
),
2294 case TEST_ARG_SAMPLER
: {
2295 cl_sampler sampler
= piglit_cl_create_sampler(
2297 test_arg
.sampler_normalized_coords
,
2298 test_arg
.sampler_addressing_mode
,
2299 test_arg
.sampler_filter_mode
);
2306 arg_set
= piglit_cl_set_kernel_arg(kernel
,
2312 add_dynamic_array((void**)&sampler_args
,
2321 printf("Failed to set kernel argument with index %u\n",
2323 clReleaseKernel(kernel
);
2324 free_mem_args(&mem_args
, &num_mem_args
);
2325 free_sampler_args(&sampler_args
, &num_sampler_args
);
2330 for(j
= 0; j
< test
.num_args_out
; j
++) {
2331 bool arg_set
= false;
2332 struct test_arg test_arg
= test
.args_out
[j
];
2334 switch(test_arg
.type
) {
2335 case TEST_ARG_VALUE
:
2336 // not accepted by parser
2338 case TEST_ARG_BUFFER
: {
2341 struct mem_arg mem_arg
;
2342 mem_arg
.index
= test_arg
.index
;
2343 mem_arg
.type
= CL_MEM_OBJECT_BUFFER
;
2345 for(k
= 0; k
< num_mem_args
; k
++) {
2346 if(mem_args
[k
].index
!= mem_arg
.index
)
2349 if(mem_args
[k
].type
!= mem_arg
.type
) {
2350 printf("Inconsistent types specified for in-out"
2351 "argument %d: arg_in: %s, arg_out: %s.\n",
2353 piglit_cl_get_enum_name(mem_args
[k
].type
),
2354 piglit_cl_get_enum_name(mem_arg
.type
));
2361 if(arg_set
|| fail
) {
2365 if(test_arg
.value
!= NULL
) {
2366 mem_arg
.mem
= piglit_cl_create_buffer(env
->context
,
2369 if( mem_arg
.mem
!= NULL
2370 && piglit_cl_set_kernel_arg(kernel
,
2378 arg_set
= piglit_cl_set_kernel_arg(kernel
,
2385 add_dynamic_array((void**)&mem_args
,
2387 sizeof(struct mem_arg
),
2392 case TEST_ARG_IMAGE
: {
2395 struct mem_arg mem_arg
;
2396 mem_arg
.index
= test_arg
.index
;
2397 mem_arg
.type
= test_arg
.image_desc
.image_type
;
2399 for(k
= 0; k
< num_mem_args
; k
++) {
2400 if(mem_args
[k
].index
== mem_arg
.index
) {
2401 printf("Argument %d: images cannot be in-out arguments.",
2412 if(!test_arg
.value
) {
2413 printf("Image argument cannot be null.\n");
2418 mem_arg
.mem
= piglit_cl_create_image(env
->context
,
2420 &test_arg
.image_format
,
2421 &test_arg
.image_desc
);
2422 if( mem_arg
.mem
!= NULL
2423 && piglit_cl_set_kernel_arg(kernel
,
2431 add_dynamic_array((void**)&mem_args
,
2433 sizeof(struct mem_arg
),
2438 case TEST_ARG_SAMPLER
:
2439 // not accepted by parser
2444 printf("Failed to set kernel argument with index %u\n",
2446 clReleaseKernel(kernel
);
2447 free_mem_args(&mem_args
, &num_mem_args
);
2448 free_sampler_args(&sampler_args
, &num_sampler_args
);
2453 /* Execute kernel */
2454 printf("Running the kernel...\n");
2456 if(!piglit_cl_execute_ND_range_kernel(env
->context
->command_queues
[0],
2458 test
.work_dimensions
,
2459 test
.global_offset_null
? NULL
: test
.global_offset
,
2460 test
.global_work_size
,
2461 test
.local_work_size_null
? NULL
: test
.local_work_size
)) {
2462 printf("Failed to enqueue the kernel\n");
2463 clReleaseKernel(kernel
);
2464 free_mem_args(&mem_args
, &num_mem_args
);
2465 free_sampler_args(&sampler_args
, &num_sampler_args
);
2470 printf("Validating results...\n");
2472 for(j
= 0; j
< test
.num_args_out
; j
++) {
2474 bool arg_valid
= false;
2475 struct test_arg test_arg
= test
.args_out
[j
];
2477 switch(test_arg
.type
) {
2478 case TEST_ARG_VALUE
:
2479 // Not accepted by parser
2481 case TEST_ARG_BUFFER
: {
2482 struct mem_arg mem_arg
;
2484 /* Find the right buffer */
2485 for(k
= 0; k
< num_mem_args
; k
++) {
2486 if(mem_args
[k
].index
== test_arg
.index
) {
2487 mem_arg
= mem_args
[k
];
2491 if(test_arg
.value
!= NULL
) {
2492 void* read_value
= malloc(test_arg
.size
);
2494 if(piglit_cl_read_buffer(env
->context
->command_queues
[0],
2500 if(check_test_arg_value(test_arg
, read_value
)) {
2501 printf(" Argument %u: PASS%s\n",
2503 !test
.expect_test_fail
? "" : " (not expected)");
2504 if(test
.expect_test_fail
) {
2505 piglit_merge_result(&result
, PIGLIT_FAIL
);
2508 printf(" Argument %u: FAIL%s\n",
2510 !test
.expect_test_fail
? "" : " (expected)");
2511 if(!test
.expect_test_fail
) {
2512 piglit_merge_result(&result
, PIGLIT_FAIL
);
2522 case TEST_ARG_IMAGE
: {
2523 struct mem_arg mem_arg
;
2525 /* Find the right buffer */
2526 for(k
= 0; k
< num_mem_args
; k
++) {
2527 if(mem_args
[k
].index
== test_arg
.index
) {
2528 mem_arg
= mem_args
[k
];
2532 if(test_arg
.value
!= NULL
) {
2533 void* read_value
= malloc(test_arg
.size
);
2535 if(piglit_cl_read_whole_image(env
->context
->command_queues
[0],
2539 if(check_test_arg_value(test_arg
, read_value
)) {
2540 printf(" Argument %u: PASS%s\n",
2542 !test
.expect_test_fail
? "" : " (not expected)");
2543 if(test
.expect_test_fail
) {
2544 piglit_merge_result(&result
, PIGLIT_FAIL
);
2547 printf(" Argument %u: FAIL%s\n",
2549 !test
.expect_test_fail
? "" : " (expected)");
2550 if(!test
.expect_test_fail
) {
2551 piglit_merge_result(&result
, PIGLIT_FAIL
);
2561 case TEST_ARG_SAMPLER
:
2562 // Not accepted by parser
2567 printf("Failed to validate kernel argument with index %u\n",
2569 clReleaseKernel(kernel
);
2570 free_mem_args(&mem_args
, &num_mem_args
);
2571 free_sampler_args(&sampler_args
, &num_sampler_args
);
2576 /* Clean memory used by test */
2577 clReleaseKernel(kernel
);
2578 free_mem_args(&mem_args
, &num_mem_args
);
2579 free_sampler_args(&sampler_args
, &num_sampler_args
);
2586 piglit_cl_test(const int argc
,
2588 const struct piglit_cl_program_test_config
* config
,
2589 const struct piglit_cl_program_test_env
* env
)
2591 enum piglit_result result
= PIGLIT_SKIP
;
2595 /* Print building status */
2596 if(!config
->expect_build_fail
) {
2597 printf("Program has been built successfully\n");
2599 printf("Program has failed to build as expected\n");
2602 /* If num_tests is 0, then we are running a build test and the fact
2603 * that we have made it this far means that the program has built
2604 * successfully, so we can report PIGLIT_PASS.
2606 if (num_tests
== 0) {
2607 result
= PIGLIT_PASS
;
2611 for(i
= 0; i
< num_tests
; i
++) {
2612 enum piglit_result test_result
;
2613 char* test_name
= tests
[i
].name
!= NULL
? tests
[i
].name
: "";
2615 printf("> Running kernel test: %s\n", test_name
);
2617 test_result
= test_kernel(config
, env
, tests
[i
]);
2618 piglit_merge_result(&result
, test_result
);
2620 piglit_report_subtest_result(test_result
, "%s", tests
[i
].name
);
2627 printf(">> Some or all of the tests FAILED\n");
2630 printf(">> Tests skipped\n");
2633 printf(">> Some or all of the tests produced a WARNING\n");
2636 printf(">> All of the tests PASSED\n");